javascript - Hogyan készítsünk tiszta aszinkron ciklust?
A tipikus REST szabványoknak megfelelően a forrásaimat külön végpontokra és hívásokra bontottam. A két fő objektum, amiről itt szó van, a List és a Item (és természetesen egy listának van egy listája a tételekből, valamint néhány más adat is társítva van hozzá).
Tehát ha egy felhasználó szeretné lekérni a listáit, elküldhet egy Get kérést a api/Lists címre
Akkor a felhasználó talán azt szeretné, hogy megszerezze az elemeket az egyik ilyen listából, és készítsen egy GET kérést a api/ListItems/4 címre, ahol a 4 a korábbi hívás során lekért List.listId értékéből származik.
Ez mind rendben van: a options.complete attribútum a $.ajax-ban lehetővé teszi, hogy egy visszahívó metódusra mutassak, így egyszerűsíthetem ezeket a két eseményt.
De a dolgok nagyon bonyolulttá válnak, ha az összes érintett lista elemeit szeretném lekérni. Például tételezzük fel, hogy van egy könyvtári függvényem, amit makeGetRequest-nek hívnak, és amely a végpontot és a callback függvényt veszi át, hogy ez a kód tisztább legyen. Csak 3 elem lekérése a naiv módon így néz ki:
var success1 = function(elements){
var success2 = function(elements){
makeGetRequest("api/ListItems/3", finalSuccess);
}
makeGetRequest("api/ListItems/2", success2);
}
makeGetRequest("api/ListItems/1", success1);
Undorító! Ez az a fajta dolog a programozás 101-ben, amiért megütögetnek az ujjaidon, és a ciklusokra mutogatnak. De hogyan lehet ezt ciklussal csinálni, anélkül, hogy külső tárolásra kellene támaszkodni?
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!
}
És még a tárolással is, tudnom kellene, mikor mindenki végzett és visszaadta az adatait, és fel kellene hívnom egy fő függvényt, amely összegyűjti az összes adatot és csinál valamit vele.
Van gyakorlat ennek kezelésére? Ezt biztosan sokszor megoldották már korábban...
Válasz #1
Próbáljon meg egy végpont-paraméterekből álló veremet használni:
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"});
Ezután rekurzívan is megcsinálhatod a sikerkezelődben:
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)
}
És elindíthatod egyetlen hívással így:
getResources(params.shift().endpoint);
Szerkesztés:
Ahhoz, hogy mindent önállóan tartsunk és a globális hatókörön kívül maradjunk, használhatunk egy függvényt, és adhatunk neki egy visszahívást:
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);
}
Használatban:
downloadResources(function(data) {
// Do stuff with your data set
});
Válasz #2
dmck válasza valószínűleg a legjobb választás. Azonban egy másik lehetőség, hogy egy tömeges listázási opciót használj, így az API-d támogatja az olyan kéréseket, mint az api/ListItems/?id=1&id=2&id=3.
Készíthetsz egy API keresési végpontot is, ha az jobban illik a személyes esztétikádhoz.
