2012-08-02 59 views
6

遵循典型的REST標準,我將自己的資源分解爲單獨的端點和調用。這裏所討論的主要兩個對象是ListItem(當然,列表還包含項目列表以及與其關聯的一些其他數據)。如何使一個乾淨的異步循環?

因此,如果用戶想要檢索他的名單,他可能會做一個GET請求api/Lists

然後,用戶可能希望得到這些列表中的一個項目,並作出獲取到api/ListItems/4其中4被發現從前面調用中檢索到的List.listId

這一切都很好:$.ajaxoptions.complete屬性讓我指向一個回調方法,所以我可以簡化這兩個事件。

但事情變得非常混亂,如果我想獲得所有元素的問題。例如,我們假設我有一個名爲makeGetRequest的庫函數,它接受終點和回調函數,以使代碼更清晰。簡單地檢索3個元素的天真的方式導致在這:

var success1 = function(elements){ 
    var success2 = function(elements){ 
     makeGetRequest("api/ListItems/3", finalSuccess); 
    } 
    makeGetRequest("api/ListItems/2", success2); 
} 
makeGetRequest("api/ListItems/1", success1); 

令人厭惡!這是編程101中的那種東西,我們在手腕上敲擊並指向循環。但是,你怎麼能用循環來做到這一點,而不必依靠外部存儲?

for(var i : values){ 
    makeGetRequest("api/ListItems/" + i, successFunction); 
} 

function successFunction(items){ 
    //I am called i-many times, each time only having ONE list's worth of items! 
} 

甚至與存儲,我必須知道什麼時候所有已經完成,並取回自己的數據,並調用檢索所有收集到的數據,並做一些事情有它的一些主站功能。

有沒有處理這個問題的做法?這一定已經解決了很多次......

+0

JQuery $ .get和$ .each – mplungjan 2012-08-02 17:46:30

+0

是否有一個原因讓您在後端沒有路徑來爲您檢索所有內容,例如'api/ListItems/all'或類似的東西?那麼你可以避免使用任何類型的異步循環。 – jackwanders 2012-08-02 17:58:06

回答

4

嘗試使用的端點參數堆棧:

var params = []; 
var results []; 

params.push({endpoint: "api/ListItems/1"}); 
params.push({endpoint: "api/ListItems/2"}); 
params.push({endpoint: "api/ListItems/3"}); 
params.push({endpoint: "api/ListItems/4"}); 

然後你就可以在你的成功處理程序遞歸的:

function getResources(endPoint) { 

    var options = {} // Ajax Options 
    options.success = function (data) { 
     if (params.length > 0) { 
      results.push({endpoint: endpoint, data: data}); 
      getResources(params.shift().endpoint); 
     } 
     else { 
      theMasterFunction(results) 
     } 
    } 

    $.get(endPoint, options) 
} 

你可以像這樣的單個呼叫啓動它:

getResources(params.shift().endpoint); 

E DIT:

把一切都自給自足的進出全球範圍內,你可以使用一個功能,並提供一個回調:

function downloadResources(callback) { 

    var endpoints = []; 
    var results []; 

    endpoints.push({endpoint: "api/ListItems/1"}); 
    endpoints.push({endpoint: "api/ListItems/2"}); 
    endpoints.push({endpoint: "api/ListItems/3"}); 
    endpoints.push({endpoint: "api/ListItems/4"}); 

    function getResources(endPoint) { 
     var options = {} // Ajax Options 
     options.success = function (data) { 
      if (endpoints.length > 0) { 
       results.push({endpoint: endpoint, data: data}); 
       getResources(endpoints.shift().endpoint); 
      } 
      else { 
       callback(results) 
      } 
     } 
     $.get(endPoint, options) 
    } 

    getResources(endpoints.shift().endpoint); 

} 

在使用中:

downloadResources(function(data) { 
    // Do stuff with your data set 
}); 
+0

迭代失敗時,請進行遞歸,呃?非常優雅的解決方案!但是,我仍然需要找到一個地方來隱藏'params'和'results',以便它們不會在調用之間超出範圍。有什麼建議嗎?我儘量避免「全局變量」作弊。 – 2012-08-02 19:02:55

+0

@ngmiceli我建議使用包含端點數組的DownloadResources函數,然後可以將繼續回調作爲參數提供給此函數。詳情請參閱我的編輯。 – dmck 2012-08-02 19:17:31

2

dmck的答案可能是你最好賭注。但是,另一個選項是執行批量列表選項,以便您的api支持像api/ListItems /?id = 1 & id = 2 & id = 3的請求。

你也可以做一個api搜索端點,如果這更符合你的個人審美。

+0

這是一個很好的觀點,也是我完全忽略的一個非常簡單的解決方案。與@jackwanders評論很好地相處。爲我的API提供處理批量GET的能力,並將所有內容拼湊在客戶端。這仍然被認爲是RESTful嗎? – 2012-08-02 19:05:26

+0

如果您正在使用GET協議檢索數據,那麼無論該URL如何「漂亮」,都是RESTful。對於該端點應該如何工作存在一些疑問。您稱之爲「列表」,其中更合適的名稱可能是批量列表或搜索。 – Jordan 2012-08-02 19:07:01