等到多个异步函数完成后再执行

时间:2017-02-28 17:54:41

标签: javascript asynchronous

我有一个Javascript for循环,它运行一系列数据库记录(已经提取过)。

我想知道所有后续异步操作何时完成,但我似乎无法做到。

对于每条记录,代码运行许多函数,这些函数返回promises然后解析(然后触发另一个函数以获取更多信息等)。一切正常,但我无法弄清楚如何收集每个" 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();
};

关于如何构建这个的任何想法?我已尝试用各种各样的东西来推销,但是我无法弄清楚......

2 个答案:

答案 0 :(得分:1)

您完成了与AVMI_getMultipleRecordInfoFromArray中完全相同的事情:收集数组中的promises并使用$.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();
});

答案 1 :(得分:-1)

您必须禁用ajax的async属性。默认情况下,它设置为true。这意味着你不会等待你的ajax响应。这就是为什么它返回你未定义的值,你必须将其设置为false。因此,您的代码将等待您的请求完成。

所以你要做的就是。

$.ajax({
  url: '',
  type: '',
  async: false,
  success: function(data){
  }
});