在执行之前等待多个异步函数完成
我有一个Javascript for循环,它通过一系列数据库记录(已经被提取)。在执行之前等待多个异步函数完成
我想知道什么时候所有的后续异步操作已完成,但我似乎无法做到这一点。
对于每条记录,代码运行一些函数,它们返回promise然后解析(然后触发另一个函数以获取更多信息等)。这一切工作正常,但我无法弄清楚如何收集每个“FOR”迭代,并检测所有记录何时被处理。基本上,我想使用一个“throbber”,并保持跳动,直到所有处理完成。
代码如下(我已经删除了一些无关的信息)...
for (var i = 0; i < systemArray.length; i++) {
// ***** FOR EACH SYSTEM ***** //
var currRecord = systemArray[i];
// SECTION REMOVED //
// GET SYSTEM LINES
var thisSystem = AVMI_filterArray("8.9", currRecord);
var thisSystemName = thisSystem[1].value;
var thisSystemRID = thisSystem[0].value;
// GET CHILDREN RIDS
AVMI_getChildren(systemLinesTable, thisSystemRID, systemLinesFID).done(function(ridList, sysRID)
{
var thisDiv = "div#" + sysRID;
// GET RECORD INFO FOR EACH RID
AVMI_getMultipleRecordInfoFromArray(ridList, systemLinesTable).done(function(systemLinesArray)
{
if (systemLinesArray != "" && systemLinesArray != null) {
systemLinesArray = systemLinesArray.sort(propComparator("10"));
x = AVMI_tableCombiner("System Lines", systemLinesArray, systemLinesCLIST, "skip3Right hbars xsmallText");
$(thisDiv).append(x);
} else {
$(thisDiv).append("<p>No System Lines...</p>");
}
}
);
}
);
} // ***** FOR EACH SYSTEM ***** //
AVMI_throbberClose(); // THIS, OF COURSE, EXECUTES ALMOST IMMEDIATELY
这里是函数1
///////////////////////////////////////////////////////////////
// Get related records using master
///////////////////////////////////////////////////////////////
function AVMI_getChildren(AVMI_db, AVMI_rid, AVMI_fid, AVMI_recText) {
var AVMI_query = "{" + AVMI_fid + ". EX. " + AVMI_rid + "}";
var AVMI_ridList = [];
var dfd2 = $.Deferred();
$.get(AVMI_db, {
act: "API_DoQuery",
query: AVMI_query,
clist: "3",
includeRids: "1"
}).then(function(xml1) {
$(xml1).find('record').each(function(){
var AVMI_record = $(this);
var AVMI_childRID = AVMI_record.attr("rid");
AVMI_ridList.push(AVMI_childRID);
});
AVMI_throbberUpdate("Found " + AVMI_ridList.length + " " + AVMI_recText + "...");
dfd2.resolve(AVMI_ridList, AVMI_rid);
});
return dfd2.promise();
};
和功能2
///////////////////////////////////////////////////////////////
// Get record info for each array member
///////////////////////////////////////////////////////////////
function AVMI_getMultipleRecordInfoFromArray(ridList, AVMI_db, AVMI_recType) {
var promises = [];
var bigArray = [];
$.each(ridList, function (index,value) {
var def = new $.Deferred();
var thisArray = [];
$.get(AVMI_db, { //******* ITERATIVE AJAX CALL *******
act: 'API_GetRecordInfo',
rid: value
}).then(function(xml2) {
AVMI_throbberUpdate("Got " + AVMI_recType + " " + value + "...");
$(xml2).find('field').each(function() {
var $field = {};
$field.fid = $(this).find('fid').text();
$field.name = $(this).find('name').text();
$field.value = $(this).find('value').text();
thisArray.push($field);
});
thisArray = thisArray.sort(AVMI_ArrayComparator);
bigArray.push(thisArray);
def.resolve(bigArray);
});
promises.push(def);
});
return $.when.apply(undefined, promises).promise();
};
的任何想法如何构造这个?我尝试了各种各样的事情与$ .Deferred但我不能完全弄清楚它...
你做的正是你在AVMI_getMultipleRecordInfoFromArray
做同样的事情:收集承诺在数组中,并使用$.when
(或Promise.all
)等待,直到他们得到解决。
你可以简单地这里使用.map
这也需要照顾"function in a loop" problem的:
var promises = systemArray.map(function(currRecord) {
// ...
return AVMI_getChildren(...).done(...);
});
$.when.apply(undefined, promises).done(function() {
AVMI_throbberClose();
});
你应该必须禁用ajax的异步属性。默认情况下它被设置为true。这意味着你不会等待你的ajax响应。那为什么它返回你未定义的值,你必须将它设置为false。所以你的代码会等待你的请求完成。
所以你所要做的就是。
$.ajax({
url: '',
type: '',
async: false,
success: function(data){
}
});
这是一个坏主意。你想冻结用户界面吗?正确的方法是使用延期对象/承诺。 – Christoph
您正在寻找的东西像['Promise.all()'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all),如果其中一个承诺被拒绝,它将等待所有承诺解决或拒绝。 – Christoph