Exploring the world of reactive programming in JavaScript by transforming traditional AJAX calls into Bacon.js streams while incorporating

How can I develop a method to convert calls to the server API to a Bacon.js / RxJs stream while supporting pagination?

With pagination, I aim to keep track of the last requested item index and retrieve the next set of items based on the page size to populate the stream.

My main requirement is to trigger the 'load next page_size items' function only when all existing items in the stream have been consumed.

Below is a test scenario I created:

var PAGE_SIZE = 20;
var LAST_ITEM = 100;
var FIRST_ITEM = 0;

function fetchItemsFromServer(fromIndex) {
    if (fromIndex > LAST_ITEM) { 
        return [];
    }

    var remainingItemsCount = LAST_ITEM - fromIndex;
    
    if (remainingItemsCount <= PAGE_SIZE) {
        return _.range(fromIndex, fromIndex + remainingItemsCount);
    }
    
    return _.range(fromIndex, fromIndex + PAGE_SIZE);
}

function createStream() {
    return Bacon.fromBinder(function(sink) {
        var fromIndex = FIRST_ITEM;

        function loadMoreItems() {
            var items = fetchItemsFromServer(fromIndex);
            fromIndex = fromIndex + items.length;
            return items;
        }

        var moreItemsAvailable = true;

        while (moreItemsAvailable) {
            var items = loadMoreItems();
            
            if (items.length < PAGE_SIZE) { 
                moreItemsAvailable = false; 
            }
            
            _.forEach(items, function(item) { sink(new Bacon.Next(item)); });
        }        

        return function() { console.log('done'); };
    });
}

createStream().onValue(function(value) {
    $("#events").append($("<li>").text(value))
});

http://jsfiddle.net/Lc2oua5x/10/

Currently, the 'fetchItemsFromServer' function simply generates items locally. How can I integrate it with an AJAX call or a promise that returns an array of items? The execution should be able to happen multiple times depending on the server's item count and the specified page size.

I looked into using Bacon.fromPromise() as per the documentation but faced difficulties in incorporating it effectively alongside the pagination logic.

Answer №1

To map pages to streams using flatMap with Bacon.fromPromise, check out this example below. It demonstrates the use of the jsfiddle echo endpoint, which sends back the same data.

Bacon.sequentially(0, _.range(0,5))
.map(toIndex)
  .flatMap(loadFromServer)
  .onValue(render)

function toIndex(page) {
    return page * PAGE_SIZE
}

function loadFromServer(index) {
    var response = getItemsFromServer(index)
    return Bacon.fromPromise($.ajax({
      type: 'POST',
      dataType: 'json',
      url: '/echo/json/',
      data : { json: JSON.stringify( response ) }
    }))
}

function render(items) {
    items.forEach(function(item) {
        $("#events").append($("<li>").text(item))
    })
}

http://jsfiddle.net/1eqec9g3/2/

Please note that this code assumes responses from the server will arrive in the order they were sent.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it advisable to prevent Set and Map from having unspecified generics in TypeScript?

Upon reviewing some old code that I wrote, I realized that I had neglected to specify a generic type for a Set. The type was set as Set<unknown>. Strangely, despite this, I found that I could still utilize all the methods of the Set without encounter ...

Unable to establish a local dependency link with npm

Attempting to connect my local project testabc123 to myproject using the usual method: cd testabc123 npm link cd ../myproject npm link testabc123 However, encountering an error message: npm ERR! code E404 npm ERR! 404 Not Found - GET http://registry.npmjs ...

Encountering a rendering error with Jest while trying to load a functional child component

I encountered an error message stating Error: Uncaught [Error: Child(...): Nothing was returned from render while testing the Parent component. Below are the relevant files that were involved: /components/Page/Children/Child.js import React from "re ...

Deleting items from an array in ReactJS

When retrieving a list of users from AWS Cognito, everything works flawlessly. However, the task of iterating over this array and removing users that do not match a specific Client ID is where I'm facing difficulties. What am I doing wrong in this sc ...

Dealing with various menu states using Material-UI Menu component: Tips and Tricks

I've encountered an issue with my dynamically generated dropdowns and accordions that appear at the client-side render (based on validated user purchases from the database). The error seems to stem from my menu anchor element not being able to pinpoi ...

Is there a way to reset or completely remove the `infiniteajaxscroll` V3 module?

Is there a way to reset or remove Infinite Ajax Scroll on version 3 without using jQuery? I am currently utilizing Import @webcreate/infinite-ajax-scroll. The documentation does not seem to provide instructions for reinitialization or destruction () Infi ...

Add an array as a nested child within another array using node.js and JavaScript

Description: I execute a MySQL query to retrieve rows from a table > connection.query(q2,function(err,rows){...} Assuming the rows have a structure like {id:",,,", time:"..." etc:"cc"} For each row, I then query another table to fetch additional dat ...

Tips on restricting users to choose dates that are later than the current date

Currently, I am working with Vue3 using the options API. After reviewing this StackBlitz, my question is regarding how to correctly set the :max value for a date-picker. Even though I have assigned :max as new Date(), I am still able to select dates that ...

Removing and shattering data from a JSON file at a designated location in AngularJS

I have received json data that is structured like this (and unfortunately cannot be modified): Desc: First data - Second data My current method of displaying this data involves using the following code: <div ng-repeat="b in a.Items">{{b.Desc}}< ...

Creating a database using Angular2+ in CouchDB can be achieved by following these steps

I have been attempting to set up a database in couchdb using angular2+. My goal is to create a button that, when clicked, will initiate the creation of the database. However, I keep encountering an error message. "ERROR Error: Uncaught (in promise): H ...

Tips for concealing a product item when the price is listed as 0

I am facing an issue where some of my products have a price of 0. In order to address this problem, I would like to hide those products from the collection pages. My question is: How can I hide the .productItem or .ItemOrj if the .productPrice span is eq ...

Developing a custom edit template with Infragistics through coding

Currently, our team utilizes the Infragistics grid without binding datasets until runtime. Instead, we set up the grid settings in code as per the preference of our senior developer. While effective, this method can seem a bit lengthy. I am interested in ...

Using Javascript, load a URL by making a JQuery ajax GET request and specifying custom headers

I currently have a small single-page application (SPA) using JQuery/Ajax for the frontend and Node/Express for the backend. The user authentication and authorization are handled with JSON-Webtoken, but I encountered an issue. If someone tries to access the ...

Retrieve information following an Ajax call inside a pre-designed template

Upon rendering a page with data put together by EJS, the goal is to refresh a section (thirdRow) of the page whenever the user submits new data. The refreshed section should display both the newly submitted data and the existing data. Although I have obtai ...

When attempting to add mp3 files to a Vue/TypeScript application, a "Module not found" error is triggered

I am encountering an error while trying to import .mp3 files into my Vue/Typescript app. Upon running 'npm serve', I am presented with the following message: ERROR in /Users/***/***/application/src/components/Sampler.vue(80,16): 80:16 Cannot fin ...

Repetitive attempts have led to the cancellation of the AJAX and PHP petition statuses

Whenever I click the button, I am trying to update a MySQL table using AJAX jQuery. Unfortunately, I am encountering a problem where the AJAX jQuery does not work properly sometimes. It starts off fine, but after a certain number of attempts, it stops work ...

Retrieve information from a pair of models

Hey there, I need some help. Can someone please guide me on how to obtain the 'topics' array and append it to res.view()? I've tried multiple approaches but keep getting 'undefined' in the 'topics' array. Subjects.qu ...

Utilizing Ajax to send a parameter to a separate PHP script

I have a dilemma that I need help with. Currently, I have a table displaying data using PHP and SQL in the following format: What I want to achieve is to be able to click a button, retrieve the ID value, and based on that, execute another SQL query to dis ...

Can anyone offer assistance with storing data in a database?

I'm having trouble saving or inserting data into my Purchase table in the database. The Save button doesn't seem to be working and no errors are being displayed. I've included my AJAX method below which is used for posting data to the contro ...

What is the ultimate Ajax toolkit available?

Which toolkit will emerge as the leader for Ajax development in the future? I have been immersed in Ajax development for years, and it seems that a new toolkit gains popularity every year. I initially used plain XHR, then transitioned to GWT, followed by ...