【问题标题】:Cannot figure out how to chain nested promise with Q无法弄清楚如何用 Q 链接嵌套的承诺
【发布时间】:2014-05-22 00:59:39
【问题描述】:

我是 node.js 和 promise (Q) 的新手,所以请善待。 我想将嵌套的 Promise 与他正在执行的父链链接起来,但我找不到如何去做。

我制作了一个玩具脚本来说明我的 pb,您可以使用 node.js 启动它:

var Q = require("q");

function init() {
    return {nbIn: 0, nbOut: 0, stop: false};
}

function fn1(ctx) {
    var deferred = Q.defer();

    console.log("fn1:" + JSON.stringify(ctx));
    setTimeout(function() {
        console.log("fn1: resolve");
        deferred.resolve(ctx);
    }, 1000)

    return deferred.promise;
}

function sub1(ctx) {
    var deferred = Q.defer();

    console.log("sub1:" + JSON.stringify(ctx));
    setTimeout(function() {
        ++ctx.nbIn;
        console.log("sub1: resolve");
        deferred.resolve(ctx);
    }, 1000);

    return deferred.promise;
}

function sub2(ctx) {
    var deferred = Q.defer();

    console.log("sub2:" + JSON.stringify(ctx));
    setTimeout(function() {
        ++ctx.nbOut;
        if(ctx.nbOut === 3) {
            console.log("sub2: resolve");
            ctx.stop = true;
            deferred.resolve(ctx);
        }
        else {
            console.log("sub2: promise");
            return sub1(ctx).then(sub2);
        }
    }, 1000);

    return deferred.promise;
}

function fn2(ctx) {
    console.log("fn2:" + JSON.stringify(ctx));
    return sub1(ctx).then(sub2);
}

function fn3(ctx) {
    console.log("fn3:" + JSON.stringify(ctx));
}

Q.fcall(init).then(fn1).then(fn2).then(fn3);

它显示:

fn1:{"nbIn":0,"nbOut":0,"stop":false}
fn1: resolve
fn2:{"nbIn":0,"nbOut":0,"stop":false}
sub1:{"nbIn":0,"nbOut":0,"stop":false}
sub1: resolve
sub2:{"nbIn":1,"nbOut":0,"stop":false}
sub2: promise
sub1:{"nbIn":1,"nbOut":1,"stop":false}
sub1: resolve
sub2:{"nbIn":2,"nbOut":1,"stop":false}
sub2: promise
sub1:{"nbIn":2,"nbOut":2,"stop":false}
sub1: resolve
sub2:{"nbIn":3,"nbOut":2,"stop":false}
sub2: resolve

我想将最后一行sub2fn3 链接起来。

任何帮助表示赞赏,谢谢。

【问题讨论】:

    标签: javascript node.js promise q


    【解决方案1】:
    setTimeout(function() {
        …
        return sub1(ctx).then(sub2);
    }, …)
    

    在这里,您尝试从异步普通回调中return。你不能这样做,结果会丢失,因为setTimeout 不关心它。

    您只能从.then() 回调中获得return。在你的情况下,它看起来像这样:

    function sub2(ctx) {
        var deferred = Q.defer();
    
        console.log("sub2:" + JSON.stringify(ctx));
        setTimeout(function() {
            deferred.resolve(ctx);
        }, 1000);
    
        return deferred.promise.then(function(ctx) {
            ++ctx.nbOut;
            if (ctx.nbOut === 3) {
                console.log("sub2: resolve");
                ctx.stop = true;
                return ctx;
            } else {
                console.log("sub2: promise");
                return sub1(ctx).then(sub2);
            }
        });
    }
    

    您还可以看到,您现在总是将Q.defersetTimeout 一起使用。您应该为返回承诺的对象创建一个辅助函数,以及 use deferreds as seldom as possible

    【讨论】:

    • 好的,我明白了。 setTimeout只是用来模拟真正的异步函数,比如db.connect/query/insert
    • 嗯,这个论点也适用于它们:将它们尽可能紧密地包装在只吐出承诺而不进行处理的辅助函数(或create those programmatically)中。使用这些承诺执行所有数据操作和流逻辑。
    猜你喜欢
    • 2015-02-26
    • 1970-01-01
    • 2013-04-03
    • 2021-05-17
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 2013-11-05
    • 2015-04-15
    相关资源
    最近更新 更多