Commençons par la règle générale d'utilisation des promesses :
Chaque fonction qui fait quelque chose de manière asynchrone doit renvoyer une promesse
De quelles fonctions s'agit-il dans votre cas ? C'est getPrayerInCat
, le forEach
rappel et Prayer.find
.
Hum, Prayer.find
ne renvoie pas de promesse, et c'est une fonction de bibliothèque donc nous ne pouvons pas la modifier. La règle 2 entre en jeu :
Créez un wrapper immédiat pour chaque fonction qui ne le fait pas
Dans notre cas, c'est facile avec les assistants d'interface de nœud de Q :
var find = Q.nbind(Prayer.find, Prayer);
Maintenant nous n'avons plus que des promesses autour, et n'avons plus besoin de report. La troisième règle entre en jeu :
Tout ce qui fait quelque chose avec un résultat asynchrone va dans un
.then
rappel
… et renvoie le résultat. Enfer, ce résultat peut même être une promesse si "quelque chose" était asynchrone ! Avec cela, nous pouvons écrire la fonction de rappel complète :
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
});
}
Maintenant, nous avons quelque chose d'un peu plus compliqué :une boucle. Appel répété de getPrayerCount()
nous obtiendra plusieurs promesses, dont les tâches asynchrones s'exécutent en parallèle et se résolvent dans un ordre inconnu. Nous voulons les attendre tous - c'est-à-dire obtenir une promesse qui se résout avec tous les résultats lorsque chacune des tâches est terminée.
Pour des tâches aussi compliquées, n'essayez pas de trouver votre propre solution :
Vérifiez l'API de votre bibliothèque
Et là on trouve Q.all
, qui fait exactement cela. Écrire getPrayerInCat
est un jeu d'enfant maintenant :
function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Si nous devions faire quoi que ce soit avec le tableau que Q.all
se résout à, appliquez simplement la règle 3.