Beginnen wir mit der allgemeinen Regel für die Verwendung von Promises:
Jede Funktion, die etwas Asynchrones macht, muss ein Promise zurückgeben
Welche Funktionen sind das in Ihrem Fall? Es ist getPrayerInCat
, der forEach
Callback und Prayer.find
.
Hm, Prayer.find
gibt kein Versprechen zurück, und es ist eine Bibliotheksfunktion, sodass wir sie nicht ändern können. Regel 2 kommt ins Spiel:
Erstellen Sie einen sofortigen Wrapper für jede Funktion, die dies nicht tut
In unserem Fall ist das mit Qs Node-Interface-Helfern einfach:
var find = Q.nbind(Prayer.find, Prayer);
Jetzt haben wir nur noch Zusagen und brauchen keine Aufschiebungen mehr. Dritte Regel kommt ins Spiel:
Alles, was etwas mit einem asynchronen Ergebnis macht, geht in ein .then
Rückruf
…und gibt das Ergebnis zurück. Verdammt, dieses Ergebnis kann sogar ein Versprechen sein, wenn "etwas" asynchron war! Damit können wir die komplette Callback-Funktion schreiben:
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
});
}
Jetzt haben wir etwas komplizierteres:eine Schleife. Wiederholtes Aufrufen von getPrayerCount()
erhält uns mehrere Promises, deren asynchrone Tasks parallel laufen und in unbekannter Reihenfolge aufgelöst werden. Wir wollen auf alle warten - d. h. ein Versprechen erhalten, das mit allen Ergebnissen aufgelöst wird, wenn jede der Aufgaben erledigt ist.
Versuchen Sie nicht, sich für solch komplizierte Aufgaben eine eigene Lösung auszudenken:
Prüfen Sie die API Ihrer Bibliothek
Und dort finden wir Q.all
, die genau das tut. Schreiben von getPrayerInCat
ist jetzt ein Kinderspiel:
function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Wenn wir irgendetwas mit dem Array machen müssten, das Q.all
beschließt, wende einfach Regel 3 an.