Javascript 循环中的多个异步函数调用
我有一堆文件要迭代。对于每个文件,根据某些字段值的不同,我可能需要或不需要发出异步AJAX请求来获取额外的数据。解决所有这些请求后,我想在继续下一个文件之前,将该文件的相关数据附加到网页。我的实际代码包含不相关的信息,但逻辑类似于以下伪代码:Javascript 循环中的多个异步函数调用,javascript,asynchronous,promise,jquery-deferred,Javascript,Asynchronous,Promise,Jquery Deferred,我有一堆文件要迭代。对于每个文件,根据某些字段值的不同,我可能需要或不需要发出异步AJAX请求来获取额外的数据。解决所有这些请求后,我想在继续下一个文件之前,将该文件的相关数据附加到网页。我的实际代码包含不相关的信息,但逻辑类似于以下伪代码: var chain = $.when(); for(x = 0; x < files.length; x++) { console.log('FOO'); chain = chain.then(function() {
var chain = $.when();
for(x = 0; x < files.length; x++) {
console.log('FOO');
chain = chain.then(function() {
var fieldNamePromises = [];
var fieldName2Promises = [];
if ('fieldName' in files[x]) {
//getFieldNameData returns an AJAX request
fieldNamePromises.push(getFieldNameData())
}
if ('fieldName2' in files[x]) {
//getField2NameData returns an AJAX request
fieldName2Promises.push(getFieldName2Data())
}
Promise.all(fieldNamePromises.concat(fieldName2Promises)).then(function() {
console.log('BAR');
})
});
}
鉴于我想要:
'FOO'
'BAR'
'FOO'
'BAR'
'FOO'
'BAR'
在继续循环之前,如何强制它等待所有异步请求完成
下面还会生成三个FOO,后面跟着三个BAR,而不是FOO-BAR交替
getFileHistory(fileNumber, function (files) {
var chain = $.when();
for (let x = 0; x < files.length; x++) {
chain = chain.then(function () {
console.log('FOO');
var fieldNamePromises = [];
fieldNamePromises.push(getData('Data', function () { }))
fieldNamePromises.push(getData('Data', function () { }))
return Promise.all(fieldNamePromises).then(function () {
console.log('BAR');
})
});
}
});
function getFileHistory(fileNumber, callback) {
var url = window.baseUrl + "api/get-file-history/filter?fileNumber=" + fileNumber;
return $.ajax({
type: 'GET',
url: url,
contentType: 'application/json; charset=utf-8',
dataType: "json",
success: function (result) {
callback(result);
}
});
}
function getData(id, callback) {
var url = "api/" + id;
return $.ajax({
type: 'GET',
url: url,
contentType: 'application/json; charset=utf-8',
dataType: "json",
success: function (result) {
callback(result);
},
error: function (error) {
console.log(error);
}
});
}
getFileHistory(文件号、函数(文件){
var chain=$.when();
for(设x=0;x
更新:当我从getFileHistory(另一个AJAX调用)中删除循环时,它会按预期返回FOO/bar。不完全清楚为什么会有不同。尝试为它创建一个不同的函数,如下面的异步函数
async function(){
var chain = $.when();
for(x = 0; x < files.length; x++) {
console.log('FOO');
chain = await chain.then(async() => {
var fieldNamePromises = [];
var fieldName2Promises = [];
if ('fieldName' in files[x]) {
//getFieldNameData returns an AJAX request
fieldNamePromises.push(getFieldNameData())
}
if ('fieldName2' in files[x]) {
//getField2NameData returns an AJAX request
fieldName2Promises.push(getFieldName2Data())
}
await Promise.all(fieldNamePromises.concat(fieldName2Promises)).then(function() {
console.log('BAR');
})
});
}
}
async函数(){
var chain=$.when();
对于(x=0;x{
var FieldNamePromissions=[];
变量fieldName2Promises=[];
如果文件[x]中有('fieldName')){
//getFieldNameData返回一个AJAX请求
推送(getFieldNameData())
}
如果文件[x]中有('fieldName2')){
//getField2NameData返回一个AJAX请求
fieldName2Promises.push(getFieldName2Data())
}
等待Promise.all(fieldnamespromises.concat(fieldName2Promises))。然后(function(){
console.log('BAR');
})
});
}
}
虽然保证了数组顺序,但每个AJAX调用可能需要不同的时间返回。我建议将它们链接起来,而不是一次全部执行。在callOne.then(callTwo.then(callThree))
中,由于每个AJAX调用可能需要调用,也可能不需要调用,因此构建这样的链将非常难看,如果可能的话(实际代码要复杂得多)。不知道是否有更干净的选择。@Dementic下面的代码仍然返回“FOO FOO BAR”而不是“FOO BAR FOO BAR”-你知道为什么吗?对于(x=0;xFOO,FOO,FOO,BAR,BAR
。对于FOO,BAR,FOO,BAR
,将console.log(FOO)
行移动到外部then()
中,同样重要的是,返回Promise.all(…)。然后(…)
。如果没有退货
,则链不会被通知承诺的结算。所有(…)。然后(…)
。谢谢。我应该提到我做了这件事,它很有效……但我需要这件事来为IE工作,不支持async/await。不,不要这样做。避免!如果你想使用async
/await
,请彻底地做,并完全删除链。
async function(){
var chain = $.when();
for(x = 0; x < files.length; x++) {
console.log('FOO');
chain = await chain.then(async() => {
var fieldNamePromises = [];
var fieldName2Promises = [];
if ('fieldName' in files[x]) {
//getFieldNameData returns an AJAX request
fieldNamePromises.push(getFieldNameData())
}
if ('fieldName2' in files[x]) {
//getField2NameData returns an AJAX request
fieldName2Promises.push(getFieldName2Data())
}
await Promise.all(fieldNamePromises.concat(fieldName2Promises)).then(function() {
console.log('BAR');
})
});
}
}