React - Controlling multiple Ajax Calls

强颜欢笑 提交于 2019-12-01 22:40:29

The async module has a function for this: async.queue. First you define a task function. Then you give it a task - in your case, an array of rows and the action you want it to take. The task will be run, or added to the queue if there is already a task in progress. When a task is completed, the next one will be taken from the queue.

Better yet, you could define the task function for just one row and set the concurrency of the queue to 5. When the user clicks the button, you add lots of tasks to the queue, one for each row that was selected. 5 tasks will start running immediately, and the rest will be queued. This is probably better than what you're trying to do, because this way the user can start 2 tasks and then immediately start another 3, and they will all run in parallel.

Try the following code:

const async = require('async');    // or whatever mechanism you're using for module management.

const queue = async.queue((row, callback) => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${call}`)
        .then(callback, callback);
}, 5);

function onGridRowsSelection(selectedRows) {
    for (let call of selectedRows) {
        queue.push(call);
    }
}

This is bound to happen because in your code, there is no check to see if already a batch request is running or not. You will have to make some changes in your code to accommodate batch calls correctly.

Step 1:

First of all, keep a flag in your state to see if already a batch request is running, say flagBatchRunning. Make it to true in your makeBatchCalls function before firing the requests.

Now once the Promise.all is resolved and all requests have completed, make it to false again.

In your action creator, check for this flag to be false.

function onGridRowsSelection(selectedRows) {
  if(!state.flagBatchRunning){
    makeBatchCalls(selectedRows,5)
  }
}

Step 2:

Simply keeping a flag won't help you because it is quite possible that a user again clicks the bulk action button while your batch call is running and your onGridRowsSelection will ignore this update in this case. So, now you need to keep some kind of variable to store these pending batch requests.

To cater this, create an array say, pendingRequestsArray. Keep adding all your pending updates in this array and once previous batch is completed, pick all the requests from pending Array and make a batch call for them.

So your function now changes to this.

// Action creator, selectedRows is an array.
function onGridRowsSelection(selectedRows) {
   if(!state.flagBatchRunning){
      makeBatchCalls(selectedRows,5)
   }else{
      state.pendingRequestsArray.push(selectedRows); //push to pending array
   }
}

async function makeBatchCalls(selectedRows, length) {
    let test = arrayIds.reduce((rows, key, index) => (index % length == 0 
                ? rows.push([key]) 
                : rows[rows.length-1].push(key)) && rows, []);
    let Batchresults = []; //convert them to two dimensionl arrays of given length [[1,2,3,4,5], [6,7,8,9,10]]
    for (calls of test) {
            Batchresults.push(await Promise.all(calls.map((call)=>{
                fetch(`https://jsonplaceholder.typicode.com/posts/${call}`) 
                })
            ));
    }
return Promise.all(Batchresults)
              .then(function(results){
                //call callback function here
                promiseResolved();
              }); //wait for all batch calls to finish
}

//assuming you have a callback function like this once all your batch calls finish
function promiseResolved(){
    //set flagRunning to false
    state.flagBatchRunning = false;

    //if any pending requests are present, process them, else ignore
    if(state.pendingRequestsArray.length > 0){
      state.flagBatchRunning = true;
      makeBatchCalls(pendingRequestsArray, pendingRequestsArray.length);
    }
}

PS. This is just a pseudo code. Do not put logic in your action creator. It should be taken care of by reducer(to change state) and saga/thunk for async actions.

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!