Vamos começar com a regra geral para usar promessas:
Toda função que faz algo assíncrono deve retornar uma promessa
Quais funções são essas no seu caso? É
getPrayerInCat
, o forEach
retorno de chamada e Prayer.find
. Hm,
Prayer.find
não retorna uma promessa e é uma função de biblioteca, portanto, não podemos modificá-la. A regra 2 entra em jogo:
Crie um wrapper imediato para cada função que não
No nosso caso, isso é fácil com os auxiliares de interface de nó do Q:
var find = Q.nbind(Prayer.find, Prayer);
Agora temos apenas promessas por aí, e não precisamos mais de adiamentos. A terceira regra entra em jogo:
Tudo o que faz algo com um resultado assíncrono vai para um.then
retorno de chamada
…e retorna o resultado. Inferno, esse resultado pode até ser uma promessa se "algo" for assíncrono! Com isso, podemos escrever a função callback completa:
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
});
}
Agora, temos algo um pouco mais complicado:um loop. Chamando repetidamente
getPrayerCount()
nos dará várias promessas, cujas tarefas assíncronas são executadas em paralelo e resolvidas em ordem desconhecida. Queremos esperar por todos eles - ou seja, obter uma promessa que resolva com todos os resultados quando cada uma das tarefas for concluída. Para tarefas tão complicadas, não tente encontrar sua própria solução:
Verifique a API da sua biblioteca
E lá encontramos
Q.all
, que faz exatamente isso. Escrevendo getPrayerInCat
é uma brisa agora:function getPrayerInCat(data) {
var promises = data.map(getPrayerCount); // don't use forEach, we get something back
return Q.all(promises);
// ^^^^^^ Rule 1
}
Se precisássemos fazer alguma coisa com o array que
Q.all
resolve, basta aplicar a Regra 3.