2016-04-13 27 views
1

問題是asked before,但是差不多是四年前,也許有更好的解決方案。

我有一個$ .each循環,其中有時其他數據正在通過ajax獲取。

我正在用提取的數據構建一個對象,循環後有一個函數可以從對象中生成HTML。 問題是循環在ajax數據到達之前完成。如果我在HTML生成函數中放置一個警報,則內容正確加載。

我正在尋找一種僅在循環和所有ajax調用完成時調用HTML生成器函數的解決方案。也許這是一個解決方案來計算已啓動的Ajax請求並等待它們全部完成?

我相信推遲jQuery是我的正確解決方案,但我確實只找到所有內容都停留在循環中的示例。有人可以幫忙嗎?

我有我的代碼精簡到最重要的事情:

//goes through each testplace -->main loop 
$.each(jsobject, function(key, value) 
{ 
//build object together... 
    for (var i = 0, numComputer = jenkinsComputer.contents.computer.length; i < numComputer; i++) 
    { 
    //If the testplace is in both objects then fire AJAX request 
    if (jenkinsComputer.contents.computer[i].displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time 
    { 
     //next $.each-iteration should only happen when received the JSON 
     var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url; 
     $.when($.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1")).done(function(jenkinsUser) 
     { 
     //build object together... 
     }); 
    } 
    } 

}); //End of main Loop ($.each) 
generateHTML(builtObject); 

這將是巨大的,如果有人能夠給我一個建議如何做到這一點。

+1

只是一個小提示:AJAX在一個循環是不是一個好主意。這看起來可能更簡單,但最好讓服務器端執行循環。 –

+0

整個腳本正在我們的本地網絡上運行,並且大部分時間只有5-10個短的ajax調用,所以這裏沒有網絡問題。如果有javascript解決方案,那將會很棒。 – bademeister

回答

0

我會做這樣的事情:

var thingstodo = $(jsobject).length; 
var notfired = true; 
$.each(jsobject, function(key, value) 
{ 
//build object together... 
    for (var i = 0, numComputer = jenkinsComputer.contents.computer.length; i < numComputer; i++) 
    { 
    //If the testplace is in both objects then fire AJAX request 
    if (jenkinsComputer.contents.computer[i].displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time 
    { 
     //next $.each-iteration should only happen when received the JSON 
     var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url; 
     $.when($.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1")).done(function(jenkinsUser) 
     { 
     //build object together... 
     thingstodo--; 
     if(thingstodo === 0 && notfired){ 
      notfired = false; 
      generateHTML(buildObject); 
     } 
     }); 
    }else{ 
     thingstodo--; 
    } 
    } 

}); //End of main Loop ($.each) 
if(thingstodo === 0 && notfired){ 
    generateHTML(buildObject); 
} 
0

這是關於解決方案的未經測試的短暫示例。我希望這給你一個想法。

// I guess that jsobject is array .. 
// if it is not object you can use something like: 
// var keys = Object.getOwnPropertyNames(jsobject) 
(function() { 
    var dfd = $.Deferred(); 

    function is_not_finished() { 
     return jsobject.length > 0 && jenkinsComputer.contents.computer.length > 0; 
    } 

    (function _handleObject() { 
     var key = jsobject.shift(); 
     var displayName = jenkinsComputer.contents.computer.shift().displayName; 

     if (displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time 
     { 
      //next $.each-iteration should only happen when received the JSON 
      var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url; 
      $.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1").done(function(jenkinsUser) 
      { 
       //build object together... 
       if(is_not_finished()) { 
        setTimeout(_handleObject,0); 
       } else { 
        dfd.resolve(); 
       } 
      }); 
     } else if (is_not_finished()) { 
      setTimeout(_handleObject,0); 
     } else { 
      dfd.resolve(); 
     } 
    }()); 

    return dfd.promise(); 
}()).done(function() { 
    generateHTML(builtObject); 
}); 
+0

您在執行ajax請求時阻止了整個執行過程,而不是讓它異步運行。 – Danmoreng

+0

嗯。實際上$。每個是同步的。如果接收數據的順序不重要,您的解決方案是OK ,因爲 您同時發送請求。這裏的關鍵是「接收時的下一次迭代」。 我們也可以開發類似$ .eachAsinc的東西,它依賴於諾言。同樣在你的情況下$ .when是不必要的,因爲$ .getJSON返回promise。 –