Javascript 循环内部的Ajax调用需要同步
我有一个编码问题,我想循环并调用一个ajax调用,但我不希望在第一个请求完成之前发送另一个请求。我尝试将其设置为asyc=false并添加onsuccess回调。但循环似乎仍在继续运行,这给了我无序的响应和并行请求 //此函数用于生成数值val,并在成功回调中传递它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
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();