0

Hinweis: Ich weiß, es gibt mehrere ähnliche beantwortete Fragen da draußen bereits, ich lese sie, aber ich habe immer noch Schwierigkeiten mit meinem Szenario.So verketten Q verzögerte Versprechen in verschachtelten Schleife mit asynchronen Firebase DB Callbacks

Ich habe eine (Google) Firebase Cloud-Funktion, die viele Abfragen in einer bestimmten Reihenfolge auch in einer Schleife ausführen muss. So etwas wie dies zum Beispiel (unter Verwendung von Lodash und Q):

let users = [foo, bar, baz, qux, etc, ...]; 
let myPromises = []; 

_.each(users, function (user) { 

    // Query A (async) 
    let queryA = function() { 
     let deferred = Q.defer(); 
     let _queryA = function() { 
      admin.database().ref('blah').child(blah).once("value", function(snapshot) { 
       // logic 
       return deferred.resolve(); 
      }); 
     }; 
     _queryA(); 
     return deferred.promise; 
    }; 

    // Query B (async) 
    let queryB = function() { 
     let deferred = Q.defer(); 
     let _queryB = function() { 
      admin.database().ref('blah').child(blah).once("value", function(snapshot) { 
       // logic 
       return deferred.resolve(); 
      }); 
     }; 
     _queryB(); 
     return deferred.promise; 
    }; 

    // Query C (async) with nested (async) query loop 
    let queryC = function() { 
     let deferred = Q.defer(); 
     let _queryC = function() { 
      admin.database().ref('blah').child(blah).once("value", function(snapshot) { 
       // logic 

       let potatoPromises = []; 

       // another query loop 
       _.each(snapshot.val(), function (potato) { 
        let potato_deferred = Q.defer(); 
        admin.database().ref('blah').child(potato.id).once("value", function(potato_snapshot) { 
         // logic 

         return potato_deferred.resolve(); 
        }); 
        potatoPromises.push(potato_deferred.promise); 
       }); 

       Q.all(potatoPromises).then(function() { return deferred.resolve() }); 
      }); 
     }; 
     _queryC(); 
     return deferred.promise; 
    }; 

    // Function D (sync) 
    let functionD() = function() { 
     let deferred = Q.defer(); 
     let _functionD = function() { 
      // logic 
     }); 
     _functionD(); 
     return deferred.promise; 
    }; 

    myPromises.push(Q.all([queryA(),queryB()]).then(queryC()).then(functionD())); 

}); 

Q.all(myPromises).then(function() { 
    // Final logic ran only once after all promises in loop are resolved 
}); 

Für jeden Benutzer wiederholt durch, queryC müssen beide starten warten, bis queryA und queryB (die in beliebiger Reihenfolge ausgeführt werden kann, damit die Q.all()) fertig sind, und functionD müssen warten, bis queryC fertig ist.

ich dachte den obigen Code würde den Trick tun, aber wenn ich die Wolke Funktion ausführen, queryA, queryB, queryC und functionD beginnen alle sofort.

Das einzige Versprechen, dass ist für mich arbeiten die letzte Logik ist einmal ganz am Ende lief, die ist warten queryA, queryB, queryC und functionD vor, wie ich beginnen möchte es to- aber die Logik innerhalb dieser letzten Funktion verwendet Informationen für jede user in queryC und functionD bestimmt, so dass es sowieso nicht richtig funktioniert.

Irgendwelche Ideen? Thanks :)

+3

'.then (queryC())' ruft sofort 'queryC' ... Sie wollen' .then (queryC) '.. usw. - Anmerkung: jedes '.then'-Argument sollte eine Funktion sein, nicht das Ergebnis des Aufrufs einer Funktion - (natürlich, wenn die aufgerufene Funktion eine Funktion liefert, die ganz in Ordnung ist, aber Ihre Funktionen keine Funktion zurückgeben) –

+1

in Zusammenfassung - myPromises.push (Q.all ([queryA(), queryB()]). dann (queryC) .then (functionD)) 'ist näher an dem, was Sie beabsichtigt haben - obwohl ich sicher bin, dass der Code sehr groß sein kann vereinfacht, da ich mir sicher bin, dass Firebase-Methoden sowieso schon ein Promise zurückgeben –

+0

Okay, ich werde das jetzt ausprobieren. Was die Firebase-Abfrage verspricht, denke ich, dass Sie Recht haben. Ich lese gerade jetzt https://firebase.googleblog.com/2016/01/keeping-our-promises-and-callbacks_76.html und es zeigt, wie ich sie verwenden kann. – WillB

Antwort

2

Versuchen, Sie Aufruf C und D:

myPromises.push(Q.all([queryA(),queryB()]).then(queryC).then(functionD)); 
Verwandte Themen