Javascript 循环内部的Ajax调用需要同步

Javascript 循环内部的Ajax调用需要同步,javascript,ajax,asynchronous,prototypejs,asynccallback,Javascript,Ajax,Asynchronous,Prototypejs,Asynccallback,我有一个编码问题,我想循环并调用一个ajax调用,但我不希望在第一个请求完成之前发送另一个请求。我尝试将其设置为asyc=false并添加onsuccess回调。但循环似乎仍在继续运行,这给了我无序的响应和并行请求 //此函数用于生成数值val,并在成功回调中传递它 function duplicateOmsid(totalAmount, omsid) { var url = '/portal/GetBulkCopyAmountServlet'; var errorString; new

我有一个编码问题,我想循环并调用一个ajax调用,但我不希望在第一个请求完成之前发送另一个请求。我尝试将其设置为asyc=false并添加onsuccess回调。但循环似乎仍在继续运行,这给了我无序的响应和并行请求

//此函数用于生成数值val,并在成功回调中传递它

  function duplicateOmsid(totalAmount, omsid) {
var url = '/portal/GetBulkCopyAmountServlet';
var errorString;


new Ajax.Request(
url, {
    method: 'post',
    parameters: {
        totalAmount: totalAmount,
        omsid: omsid
    },        
    async: false,
    onSuccess: function(transport) {
        dataResponse = transport.responseText.evalJSON();
          createWorkflow(totalAmount, omsid, dataResponse);


    },

//用于循环通过并调用重复工作流ajax调用的函数

function createWorkflow(totalAmount, omsid, bulkAmount) {
            var amountProccessed = 0; 
            for( i = 0; amountProccessed < totalAmount; i++ ) {  // Loop through source
                var duplicateAmt;

                if (totalAmount < 11){
                    duplicateAmt = totalAmount
                }else{
                     duplicateAmt = amountProccessed + dataResponse < totalAmount ? dataResponse : totalAmount - amountProccessed
                }


           duplicateWorkflow(totalAmount, omsid, duplicateAmt, amountProccessed);
           amountProccessed += bulkAmount;
    }
     }

根据经验,使用原始Javascript对异步代码进行顺序化的方法是使用递归而不是for循环

var urls = [ /*...*/ ];

function loop(i, onDone){
    if(i >= urls.length){
        //base case
        onDone( theResultOfProcessingTheAjaxRequests );
    }else{
        Ajax.Request(urls[i], {
            onsuccess: function(){
                loop(i+1, onDone);
            }
        });
    }
}

loop(0, function(result){
    console.log("all done");
});
请注意,我将
I
转换为一个函数参数,以将其范围限定为循环函数。如果需要,可以在外部声明它,就像在for循环中一样:

var urls = [ /*...*/ ];
var i = 0;

function loop(onDone){
   //...
   i = i+1;
   loop(onDone);
}
此外,我还向循环函数添加了一个“onDone”回调,以帮助异步代码看起来更像同步版本。其思想是,通过使用返回回调,
循环
函数不需要知道调用它的函数是什么,以及在完成它的工作后应该跳转到哪里-最后,调用
onDone(x)
与执行
返回x
有点类似。当然,如果需要,您可以硬编码返回函数

function afterAjax(){
    console.log("all done");
}

function loop(){
    if(i >= urls.length){
       afterAjax();
    }
    //...
}

loop();


最后,像这样编码递归循环有点烦人,有许多库提供函数来封装这些高级顺序化和并行化模式。特别是,通过回调手工处理错误(try-catch)特别困难。如果您正在做任何非三次异步的事情,我强烈建议您查看其中一些库。

最好尝试异步化循环:-)在@user3461385中没有
Async
选项:您可以单击绿色复选标记将答案标记为已接受:)(您也可以对任何您认为有用的答案进行升级)我尝试过。看来我得等到我的名声达到15岁时再回来,我才能投票接受
function afterAjax(){
    console.log("all done");
}

function loop(){
    if(i >= urls.length){
       afterAjax();
    }
    //...
}

loop();