MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Problema nella restituzione dei dati recuperati dalle query DB richiamate nel ciclo

Iniziamo con la regola generale per l'utilizzo delle promesse:

Ogni funzione che fa qualcosa di asincrono deve restituire una promessa

Quali funzioni sono queste nel tuo caso? È getPrayerInCat , il forEach richiamata e Prayer.find .

Hm, Prayer.find non restituisce una promessa ed è una funzione di libreria, quindi non possiamo modificarla. Entra in gioco la Regola 2:

Crea un wrapper immediato per ogni funzione che non lo fa

Nel nostro caso è facile con gli helper di interfaccia dei nodi di Q:

var find = Q.nbind(Prayer.find, Prayer);

Ora abbiamo solo promesse in giro e non abbiamo più bisogno di differimenti. Entra in gioco la terza regola:

Tutto ciò che fa qualcosa con un risultato asincrono va in un .then richiamata

...e restituisce il risultato. Diavolo, quel risultato può anche essere una promessa se "qualcosa" fosse asincrono! Con questo, possiamo scrivere la funzione di 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
    });
}

Ora abbiamo qualcosa di un po' più complicato:un loop. Chiamando ripetutamente getPrayerCount() ci darà più promesse, le cui attività asincrone vengono eseguite in parallelo e si risolvono in un ordine sconosciuto. Vogliamo aspettarli tutti, ovvero ottenere una promessa che si risolva con tutti i risultati al termine di ciascuno dei compiti.

Per compiti così complicati, non cercare di trovare la tua soluzione:

Controlla l'API della tua libreria

E lì troviamo Q.all , che fa esattamente questo. Scrivendo getPrayerInCat ora è un gioco da ragazzi:

function getPrayerInCat(data) {
    var promises = data.map(getPrayerCount); // don't use forEach, we get something back
    return Q.all(promises);
//  ^^^^^^ Rule 1
}

Se avessimo bisogno di fare qualcosa con l'array che Q.all risolve, basta applicare la Regola 3.