【发布时间】:2019-08-05 16:30:41
【问题描述】:
我有一堆文件要迭代。对于每个文件,根据某些字段值,我可能需要也可能不需要进行异步 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'
'FOO'
'FOO'
'BAR'
'BAR'
'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(另一个 AJAX 调用)中删除循环时,它会按预期返回 FOO/BAR。不完全确定为什么会有所作为。
【问题讨论】:
-
虽然保证了数组顺序,但每个 AJAX 调用可能需要不同的时间才能返回。我建议将它们链接起来,而不是一次全部执行。链如
callOne.then(callTwo.then(callThree)) -
由于每个 AJAX 调用可能需要也可能不需要调用,因此构建这样的链将非常难看,如果可能的话(实际代码要复杂得多)。想知道是否有更清洁的选择。
-
@Dementic 下面的代码仍然返回 'FOO FOO BAR BAR' 而不是 'FOO BAR FOO BAR' - 有什么想法吗? for (x = 0; x
-
同意这会很丑,但我认为你别无选择。
-
您的 FOO 被同步记录(在您的 for 循环中)和您的 BAR 异步记录(在以后的事件线程中),保证
FOO, FOO, FOO, BAR, BAR, BAR。对于FOO, BAR, FOO, BAR, FOO, BAR,将console.log(foo)行移到外部then()内,同样重要的是,return Promise.all(...).then(...)。没有return,链上不会收到Promise.all(...).then(...)的结算通知。
标签: javascript asynchronous promise jquery-deferred