javascript - Jak udělat čistou asynchronní smyčku?
Podle typických standardů REST jsem rozdělil své zdroje do samostatných koncových bodů a volání. Hlavními dvěma objekty, o které zde jde, jsou List a Item (a samozřejmě, seznam má seznam položek, stejně jako některá další data s ním spojená).
Takže pokud chce uživatel získat své seznamy, může provést GET požadavek na api/Lists
Pak by uživatel mohl chtít získat položky v jednom z těchto seznamů a provést GET na api/ListItems/4, kde 4 bylo nalezeno z List.listId získaného v předchozím volání.
To je všechno v pořádku: atribut options.complete $.ajax mi umožňuje odkazovat na zpětnou volací metodu, takže mohu zjednodušit tyto dvě události.
Ale věci se velmi zkomplikuju, pokud chci získat prvky pro všechny seznamy, o kterých je řeč. Například předpokládejme, že mám knihovní funkci nazvanou makeGetRequest, která přijímá koncový bod a zpětnou volací funkci, aby byl tento kód čistší. Pouhé získání 3 prvků na naivní způsob vede k tomuto:
var success1 = function(elements){
var success2 = function(elements){
makeGetRequest("api/ListItems/3", finalSuccess);
}
makeGetRequest("api/ListItems/2", success2);
}
makeGetRequest("api/ListItems/1", success1);
Odporné! To je ten druh věci, za který nás na programování 101 napomínají a ukazují na smyčky. Ale jak to můžete udělat pomocí smyčky, aniž byste museli spoléhat na externí úložiště?
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!
}
A dokonce i s ukládáním bych musel vědět, kdy všichni dokončili a získali svá data, a zavolat nějakou hlavní funkci, která získá všechna shromážděná data a něco s nimi udělá.
Existuje nějaká praxe pro řešení tohoto? To už muselo být mnohokrát vyřešeno...
Odpověď č. 1
Zkuste použít zásobník parametrů koncového bodu:
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"});
Pak to můžete udělat rekurzivně ve svém handleru úspěchu:
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)
}
A můžete ho spustit jediným voláním takto:
getResources(params.shift().endpoint);
Upravit:
Aby vše zůstalo samostatné a mimo globální oblast, můžete použít funkci a poskytnout zpětné volání:
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);
}
V použití:
downloadResources(function(data) {
// Do stuff with your data set
});
Odpověď č. 2
Odpověď dmck je pravděpodobně vaše nejlepší volba. Další možností je však použít možnost hromadného seznamu, aby vaše API podporovalo požadavky jako api/ListItems/?id=1&id=2&id=3.
Také byste mohl udělat API vyhledávací endpoint, pokud to více odpovídá vašemu osobnímu vkusu.
