Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/413.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React-控制多个Ajax调用_Javascript_Ajax_Reactjs_Promise_Axios - Fatal编程技术网

Javascript React-控制多个Ajax调用

Javascript React-控制多个Ajax调用,javascript,ajax,reactjs,promise,axios,Javascript,Ajax,Reactjs,Promise,Axios,在react应用程序中,我有一个网格。用户可以一次选择多个网格行,然后单击按钮对所选网格行执行批量操作 在服务器端,我有一个脚本,我希望在单击批量操作按钮时为每个选定行执行该脚本(为了简化问题,我在下面的示例中为每个选定行调用“jsonplaceholder.typicode.com”)。单击bulk action按钮,我在action creator中获得selectedRows,在这里我迭代selectedRows并对每个选定行进行ajax调用 由于selectedRows可能包含1000多

在react应用程序中,我有一个网格。用户可以一次选择多个网格行,然后单击按钮对所选网格行执行批量操作

在服务器端,我有一个脚本,我希望在单击批量操作按钮时为每个选定行执行该脚本(为了简化问题,我在下面的示例中为每个选定行调用“jsonplaceholder.typicode.com”)。单击bulk action按钮,我在action creator中获得selectedRows,在这里我迭代selectedRows并对每个选定行进行ajax调用

由于selectedRows可能包含1000多个项目,并且如果我只是使用forEach循环迭代地进行ajax调用,那么浏览器页面最终可能会在每个请求得到解决之前停止响应。因此,我使用下面的解决方案,以5个为一批发送请求,然后等待这5个请求得到解决

// Action creator, selectedRows is an array.
function onGridRowsSelection(selectedRows) {
   makeBatchCalls(selectedRows,5)
}

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); //wait for all batch calls to finish
}
上面的解决方案很好,但有一个问题

  • 从网格中选择5行以上,然后单击“批量操作”按钮
  • 再次选择5行以上并单击批量操作按钮
  • 现在我看到一次有10个请求处于活动状态 我如何限制这一点

    此处提到的问题的后续问题在中提出


    这个问题是

    的后续问题,这是不可避免的,因为在您的代码中,没有检查批处理请求是否已经在运行。您必须对代码进行一些更改,以正确地适应批处理调用

    步骤1:

    首先,在您的状态中保留一个标志,以查看是否已经有批处理请求正在运行,比如flagBatchRunning。在触发请求之前,在makeBatchCalls函数中将其设置为true

    现在,一旦Promise.all得到解决,并且所有请求都已完成,请再次将其设置为false

    在动作创建者中,检查此标志是否为false

    function onGridRowsSelection(selectedRows) {
      if(!state.flagBatchRunning){
        makeBatchCalls(selectedRows,5)
      }
    }
    
    步骤2:

    仅仅保留一个标志对您没有帮助,因为在批处理调用运行时,用户很可能再次单击批量操作按钮,在这种情况下,您的onGridRowsSelection将忽略此更新。因此,现在需要保留某种变量来存储这些挂起的批处理请求

    为此,创建一个数组,比如pendingRequestsArray。继续在此阵列中添加所有挂起的更新,一旦上一批完成,从挂起阵列中选取所有请求,并对它们进行批处理调用

    所以你的函数现在变为这个

    // 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);
        }
    }
    
    这只是一个伪代码。不要把逻辑放在你的行动中。它应该由reducer(改变状态)和saga/thunk负责异步操作


    希望这能有所帮助。

    异步
    模块有一个功能:。首先定义一个任务函数。然后给它一个任务——在您的例子中,是一个行数组和您希望它执行的操作。将运行该任务,或将其添加到队列(如果已存在正在进行的任务)。任务完成后,将从队列中获取下一个任务

    更好的是,您可以只为一行定义任务函数,并将队列的并发性设置为5。当用户单击该按钮时,您将向队列中添加大量任务,每选定一行一个任务。5个任务将立即开始运行,其余任务将排队。这可能比您正在尝试的要好,因为这样用户可以启动2个任务,然后立即启动另外3个任务,并且它们都将并行运行

    请尝试以下代码:

    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);
        }
    }
    

    1.谁将调用此回调?我无法区分每次单击按钮的响应。1。一旦您的所有承诺都得到解决,就应该调用此回调。检查下一组更新。更新了我的答案以显示如何呼叫回拨。谢谢你的答案,让我试试这个。