2017-01-11 56 views
2

我正在使用AJAX加載一組數據塊。這些塊中的每一個都需要按順序在DOM中呈現,所以我請求第一個塊並呈現它,然後請求以下內容,直到最後一個爲止。當最後一個完成,延期對象被解析成通知另一個函數的所有塊被裝:按順序多個AJAX成功

function loadBlock(block, limit) { 
    var deferred = $.Deferred(); 
    (function request(block, limit) { 
    $.ajax({ 
     url: 'block/' + block, 
     success: function(html) { 
     $('#block-' + block).html(html); 
     var nextBlock = block + 1; 
     if (nextBlock <= limit) 
      request(nextBlock, limit); 
     else 
      deferred.resolve(); 
     } 
    }); 
    })(block, limit); 

    return deferred.promise(); 
} 

然而,這整個等待上一個請求完成可以減緩的過程中下降了很多。

所以現在我所要做的只是將所有的請求作爲一次,並讓服務器儘可能多地做,但不是在相應的請求完成後加載每個塊,我想要一個塊等待直到前一個被加載。

示例:發送了10個請求。我們希望按照以下順序渲染這些塊:1,2,3,...假設前三個塊的請求按順序完成,因此這些塊將按照我們的需要加載到頁面中,但是接下來的塊5在塊4之前已經準備好了,我們希望將塊5保留在某個地方,並且只有在塊4存在之後,即在塊4的請求完成並且已經被渲染之後,纔將其顯示在頁面中。

我的問題,然後是:

  • 我怎麼能並行運行某些功能加載射擊在頁面塊的請求和其他功能?
  • 如何發出加載特定塊的函數,以完成上一個塊,以便它可以繼續?

另外,我需要保留延遲邏輯,因爲我仍然必須在完成整個過程時發出信號。

回答

0

如下可以做到這一點:

var loadBlockOneDef = loadBlock(block, limit); 
var loadBlockTwoDef = loadBlock(block, limit); 
... 
Promise.all([loadBlockOneDef, loadBlockTwoDef, ..]) 
    .then(function (values){ 
     //DO STUFF 
    } 

爲Promise.all參數()是承諾/ deferreds的陣列。 這些值是數組中每個承諾的數組,value [0] - > resolve-value of loadBlockOneDef,...

+0

據我瞭解這個問題,OP不希望等到所有的都完成,唯一的限制是有效載荷必須以正確的順序顯示 –

0

這可確保立即執行ajax請求,但會按順序進行解析。它總是等待先前的Deferred被解決,在解決之前的當前一個(即使當前ajax調用在前一個之前完成)。

var loadBlock = (function(previous){ 
    //the purpose of `removePreviousResponse` is to clean up 
    //the arguments returned by the Deferred 
    //and to stay consistent with the behaviour of $.ajax() 
    function cleanupArguments(previousArgs, currentArgs){ 
     //here `$.when()` is resolved with two arguments, 
     //the args for the previous and for the current ajax call 
     //we want only the args for the current ajax-call to be further propagated 

     //since we can not return multiple values, we wrap them into a Deferred 
     //that is resolved with multiple arguments 
     var deferred = $.Deferred(); 
     deferred.resolve.apply(deferred, currentArgs); 
     return deferred.promise(); 
    } 

    return function(block){ 
     //resolves when _both_ promises are done, 
     //the previous one and the current 
     var current = $.when(previous, $.get('block/' + block)) 
      .then(cleanupArguments) 
      .done(function(html, success, evt){ 
       //add html to the DOM 
       $('#block-' + block).html(html); 
      }); 

     previous = current; 
     return current; 
    } 
})(null); 

//the blocks are added in that order that you call `loadBlock()` 
loadBlock(0); 
loadBlock(1); 
loadBlock(3).then(function(html, success, evt){ 
    //you can even append further logic 
    console.log("block 3 has been loaded"); 
}); 
loadBlock(2); 
+0

你能否更詳細地解釋這是怎麼回事?另外,我不明白第一條評論。另外,延遲對象又如何保持在那裏? – dabadaba

+0

@dabadaba,我已經編輯了答案,也許現在更清楚了。我假定你的意思是如何保留「前一個」延期?它保存在''前一個''變量中,並且每次調用'loadBlock()'時都會更新以始終包含最新的延遲。我也稍微改變了清理功能中的邏輯,以產生更一致的結果。 – Thomas