MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Problema no retorno de dados recuperados de consultas de banco de dados chamadas no loop


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.