2017-01-11 13 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(); 
} 

しかし、以前の要求のために、この全体の待ち時間がたくさんプロセスを遅くすることができます完了するために:最後の1が行われた場合、繰延オブジェクトは、すべてのブロックがロードされた別の関数を通知するために解決されます。

だから私は何をしようとしているのは、一度にすべてのリクエストを起動して、できるだけ多くのサーバーを取得させることですが、対応するリクエストが完了した後に各ブロックをロードするのではなく、前のものがロードされるまで繰り返す。

例:10個のリクエストが送信されます。 1、2、3、...順番にブロックをレンダリングしたいとしましょう。最初の3つのブロックのリクエストが順番に完了しているので、ブロックがページにロードされているとしますが、ブロック5ブロック4の前に準備が整っていれば、ブロック5をどこかに保ち、ブロック4がそこにあるとき、つまりブロック4の要求が完了してレンダリングされた後にのみページに表示したいと思うでしょう。

私の質問は、以下のとおりです。

  • はどのようにして並列に実行することができますページ内のブロックを読み込み要求と他の機能を発射するいくつかの機能?
  • 前のブロックがロードされた特定のブロックをロードする機能を通知することができます。

また、遅延ロジックを維持する必要があります。なぜなら、プロセス全体が完了した時点でも信号を送信する必要があるからです。

答えて

1

そうすることの最もエレガントな方法は、より多くの初歩的な方法が完了した要求または各AJAXの後にチェックされているBooleansの配列を格納するためにintをマークするだろうPromise.all()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

を使用することですリクエストが完了しました。

+0

答えをもう少し開発できますか?私は自分のシナリオでそれをどのように統合するのかわかりません。 – dabadaba

0

次のようにあなたがそれを行うことができます。

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

をPromise.allためのパラメータは、()約束/ Deferredの作り方の配列です。 値は配列内の各約束の配列で、loadBlockOneDefのvalues [0] - > resolve-value ...

+0

私は質問を理解しているので、OPはすべてが完了するまで待たずに、ペイロードを正しい順序で表示しなければならないという唯一の制限があります。 –

0

これはajax-requestの即時実行を保証しますが、 が解決する前に、前回のDeferredが解決されるのを待っています。(現行のajax-callが前のajax-callよりも前に完了していても)を解決します。

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、私は答えを編集しました、おそらくもっと明らかになったかもしれません。私は、あなたが「以前の」延期がどのように保たれているかということを仮定していますか?これは 'previous'変数に保持され、' loadBlock() 'の各呼び出しで更新され、常に最新の遅延を含みます。また、クリーンアップ関数のロジックを少し変更してより一貫した結果を得ました。 – Thomas