MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Problem bei der Rückgabe von Daten, die von DB-Abfragen abgerufen wurden, die in der Schleife aufgerufen wurden

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.