2017-02-28 156 views
1

我有一個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但我不能完全弄清楚它...

+0

您正在尋找的東西像['Promise.all()'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all),如果其中一個承諾被拒絕,它將等待所有承諾解決或拒絕。 – Christoph

回答

1

你做的正是你在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(); 
}); 
-1

你應該必須禁用ajax的異步屬性。默認情況下它被設置爲true。這意味着你不會等待你的ajax響應。那爲什麼它返回你未定義的值,你必須將它設置爲false。所以你的代碼會等待你的請求完成。

所以你所要做的就是。

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

這是一個壞主意。你想凍結用戶界面嗎?正確的方法是使用延期對象/承諾。 – Christoph

相關問題