Javascript 循环中的多个异步函数调用

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() {

我有一堆文件要迭代。对于每个文件,根据某些字段值的不同,我可能需要或不需要发出异步AJAX请求来获取额外的数据。解决所有这些请求后,我想在继续下一个文件之前,将该文件的相关数据附加到网页。我的实际代码包含不相关的信息,但逻辑类似于以下伪代码:

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