【问题标题】:How to chain Q deferred promises in nested loop with Firebase DB async callbacks如何使用 Firebase DB 异步回调在嵌套循环中链接 Q 延迟承诺
【发布时间】:2017-10-12 11:35:19
【问题描述】:

注意:我知道已经有多个类似已回答的问题,我阅读了它们,但我的方案仍然有困难。

我有一个 (Google) Firebase Cloud Function,它需要以一定的顺序运行许多查询,也需要循环运行。例如这样的事情(使用Lodash 和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
});

对于每个迭代的用户,queryC 必须等到queryA 和queryB(可以按任何顺序运行,因此Q.all())都完成后才能启动,而functionD 必须等到@ 987654330@已完结。

我认为上面的代码可以解决问题,但是当我运行云函数时,queryA、queryB、queryC 和 functionD 都立即启动。

正在为我工作的唯一 Promise 是最后运行一次的最终逻辑,正在等待queryA、queryB、@987654337 @ 和 functionD 在开始之前像我想要的那样 - 但最终函数内部的逻辑使用为 queryC 和 functionD 中的每个 user 确定的信息,所以它无论如何都不能正常工作。

有什么想法吗?谢谢:)

【问题讨论】:

  • .then(queryC()) 立即调用 queryC ... 你想要 .then(queryC) ... 等等 - 注意:任何 .then 参数应该是一个函数,而不是调用函数的结果 - (当然如果被调用的函数返回一个很好的函数,但是你的函数不返回一个函数)
  • 总而言之 - myPromises.push(Q.all([queryA(),queryB()]).then(queryC).then(functionD))` 更接近您的预期 - 不过,我确信代码可以大大简化,因为我确信 firebase 方法已经返回了一个 Promise 反正
  • 快速且未经测试(显然)重写 - jsfiddle.net/h5r9v0b9
  • 我在您的代码中注意到的一件事 ...let queryA = () { ...这不是有效的 javascript - 所有这些代码都应该是 let queryA = () => { 或 let queryA = function() { 吗?
  • 一切都好,我猜到你的意思了

标签: node.js firebase firebase-realtime-database q google-cloud-functions


【解决方案1】:

试试看,你正在调用 C 和 D:

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

【讨论】:

    猜你喜欢
    • 2016-09-03
    • 1970-01-01
    • 2012-12-17
    • 2013-09-11
    • 2013-04-27
    • 2014-10-27
    • 2017-05-08
    • 1970-01-01
    • 2021-02-09
    相关资源
    最近更新 更多