Začněme obecným pravidlem pro používání slibů:
Každá funkce, která provádí něco asynchronního, musí vrátit příslib
O jaké funkce se ve vašem případě jedná? Je to getPrayerInCat
, forEach
zpětné volání a Prayer.find
.
Hm, Prayer.find
nevrací slib a je to funkce knihovny, takže ji nemůžeme upravit. Do hry vstupuje pravidlo 2:
Vytvořte okamžitou obálku pro každou funkci, která ne
V našem případě je to snadné s pomocníky pro rozhraní uzlů Q:
var find = Q.nbind(Prayer.find, Prayer);
Nyní máme kolem sebe jen sliby a nepotřebujeme žádné odklady. Do hry vstupuje třetí pravidlo:
Vše, co dělá něco s asynchronním výsledkem, jde do
.then
zpětné volání
...a vrátí výsledek. Sakra, ten výsledek může být dokonce příslibem, kdyby „něco“ bylo asynchronní! S tímto můžeme napsat kompletní funkci zpětného volání:
function getPrayerCount(data2) {
var id = data2.id;
return find({prayerCat:id})
// ^^^^^^ Rule 1
.then(function(prayer) {
// ^^^^^ Rule 3
if (!prayer)
data2.prayersCount = 0;
else
data2.prayersCount = prayer.length;
return data2;
// ^^^^^^ Rule 3b
});
}
Nyní máme něco trochu složitějšího:smyčku. Opakované volání getPrayerCount()
dostaneme několik slibů, jejichž asynchronní úkoly běží paralelně a řeší se v neznámém pořadí. Chceme na všechny počkat – tj. získat příslib, který se vyřeší se všemi výsledky, až bude každý z úkolů dokončen.
U takto komplikovaných úkolů se nesnažte přijít s vlastním řešením:
Zkontrolujte rozhraní API vaší knihovny
A tam najdeme Q.all
, který dělá přesně tohle. Psaní getPrayerInCat
je teď hračka:
function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Pokud bychom potřebovali něco udělat s polem, Q.all
rozhodne, stačí použít pravidlo 3.