2013-02-11 29 views
5

我需要使用有限的流進行順序異步ajax請求。截至目前,我只能在Web服務器上佔用一個流,因此我只能在一次做一個Ajax請求。如何使用給定數量的流執行順序異步ajax請求

我有以下功能,可以幫助我,當我被允許一次只能使用一個流。

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 
    } 
    } 

說,如果我有三個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服務器。目前,我一次只能執行一個請求,所以啓動鏈接函數按順序調用這三個方法。如果我有權訪問M個連接,我想執行| N |並行運行(最高可達M)。

+1

你的問題到底是什麼? – jfriend00 2013-02-11 05:13:11

+0

正如我提到的 我有一組函數N,在這種情況下getGadgets,getDeals和getDeals(| N | = 3),每個函數都需要連接到Web服務器。目前,我一次只能執行一個請求,所以啓動鏈接函數按順序調用這三個方法。如果我有權訪問M個連接,我想執行| N |並行運行(最高可達M)。 – harsha 2013-02-11 07:57:47

回答

14

如果你使用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); 
    } 

}) 
+0

謝謝。它按需要工作。 – harsha 2013-07-31 05:28:52

+0

如果它有效,您能否將答案標記爲獲勝答案。謝謝 – 2013-11-09 08:16:08

+0

這很聰明!非常感謝。 – Kevindra 2014-09-09 22:31:48

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); 
0

感謝@詹姆斯,我得到了線索,從所編輯的內容長度。因此這些調用是異步的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