7

限られたストリームで順次非同期 ajax リクエストを行う必要があります。現在、Web サーバー上で占有できるストリームは 1 つだけなので、一度に実行できる ajax リクエストは 1 つだけです。

一度に1つのストリームしか使用できない場合に役立つ次の機能があります。

function initiateChain() {
    var i = 0;
    var tasks = arguments;
    var callback = function () {
      i += 1;
      if (i != tasks.length) {
        tasks[i](callback); //block should call callback when done otherwise loop stops
      }
    }
    if (tasks.length != 0) {
      tasks[0](callback); //initiate first one
    }
  }

3 つの ajax ヘルパー関数があるとします。

 function getGadgets(callback) {
         //ajax call
         callback(); // I call this in complete callback of $.ajax
 }

 function getBooks(callback) {
         //ajax call
         callback(); // I call this in complete callback of $.ajax
 }

 function getDeals(callback) {
         //ajax call
         callback(); // I call this in complete callback of $.ajax
 }

次の呼び出しにより、このクライアントから 1 つ以上の ajax リクエストが行われないことが保証されます

initiateChain(getGadgets, getBooks, getDeals);

次に、initiateChain を拡張して、任意の数のストリームをサポートする必要があります。2 つまたは n 個のストリームを使用することが許可されているとします。ajax ヘルパー関数 getGadgets、getDeals、getDeals を変更せずにそうするためのアイデアを知りたいと思います。

つまり、一連の関数 N があります。この場合は、getGadgets、getDeals、および getDeals(|N|=3) で、それぞれ Web サーバーへの接続が必要です。現在、一度に 1 つのリクエストしか実行できないため、initiateChain 関数は 3 つのメソッドを順番に呼び出します。M 接続にアクセスできる場合、|N| を実行したいと思います。並列に機能します (最大 M まで)。

4

3 に答える 3

16

jQuery を使用している場合は、その.queueメソッドを使用して ajax 呼び出しをキューに入れ、順番に実行できます。複数のシーケンスを実行するには、最初のデキューをループでラップできます。

function add_api_call_to_queue(qname, api_url) {
    $(document).queue(qname, function() {
        $.ajax({
            type     : 'GET',
            async    : true,
            url      : api_url,
            dataType : 'json',
            success  : function(data, textStatus, jqXHR) {
                // activate the next ajax call when this one finishes
                $(document).dequeue(qname);
            }
        });
    });
}

$(document).ready(function() {

    var queue_name       = 'a_queue';
    var concurrent_calls = 2;

    // add first AJAX call to queue
    add_api_call_to_queue(queue_name, '/example/api/books');

    // add second AJAX call to queue
    add_api_call_to_queue(queue_name, '/example/api/dvds');

    // add third AJAX call to queue
    add_api_call_to_queue(queue_name, '/example/api/shoes');

    // start the AJAX queue
    for (i=0;i<concurrent_calls;i++) {
        $(document).dequeue(queue_name);
    }

})
于 2013-06-25T11:11:46.683 に答える
1

コールバックがすべて同期している限り、これはうまくいくはずです。

var initiateChain = function () {

    var args = arguments,
        index = 0,
        length = args.length,
        process = function ( index ) {

            if ( index < length ) {
                $.ajax({
                    url: '/example.php',
                    complete: function () {
                        // Callbacks get run here
                        args[ index ];
                        process( ++index );
                    }

                });
            }


        };

    if ( length ) {
        process( 0 );
    }

};

initiateChain( getGadgets, getDeals, getDeals );
于 2013-02-11T05:25:37.050 に答える
0

ありがとう@James、あなたが編集した長さから手がかりを得ました。そのため、呼び出しは非同期 ajax リクエストです。そのため、M 個の非同期呼び出しを事前に作成するという考え方があります。その後、それぞれが完了すると、それらの多くが続行されます。

私はnodejsで実験を行い、initiateChainに従って意図したとおりに動作しました

var calls = [];

function initiateChain() {
    var i = 0;
    var maxSteams = 2;
    var tasks = arguments;
    var callback = function () {
      i += 1;
      if (i < tasks.length) {
        tasks[i](callback); //block should call callback when done otherwise loop stops
      }
    }
    if (tasks.length) {
      i = ((tasks.length > maxSteams) ? maxSteams : tasks.length) - 1;
      for (var j = 0; j < maxSteams; j+=1) {
        if (j < tasks.length) {
          tasks[j](callback); //initiate first set
        } else {
          break;
        }
      }
    }
}

//test methods
for(var k = 0; k < 8; k+=1 ) {
  calls[k] = (function (message, index) {
    return function (callback) {
      var ts = new Date().getTime();
      console.log(message + " started - " + ts);
      setTimeout(function() {
        ts = new Date().getTime();
        console.log(message + " completed - " + ts);
        callback();
      }, index * 1000);
    };
  })("call" + (k+1), (k+1))
}

initiateChain(calls[0], calls[1], calls[2], calls[3], 
    calls[4], calls[5], calls[6], calls[7]);

私の実験では、次の結果が得られました

call1 started - 1360580377905
call2 started - 1360580377926

call1 completed - 1360580378937
call3 started - 1360580378937

call2 completed - 1360580379937
call4 started - 1360580379937

call3 completed - 1360580381945
call5 started - 1360580381945

call4 completed - 1360580383946
call6 started - 1360580383946

call5 completed - 1360580386959
call7 started - 1360580386959

call6 completed - 1360580389950
call8 started - 1360580389950

call7 completed - 1360580393972

call8 completed - 1360580397959
于 2013-02-11T11:03:56.983 に答える