链式Q承诺序列不会工作

时间:2015-10-20 23:24:28

标签: javascript node.js promise q

Node.js应用Q Promise的应用中,我有这段代码,我希望看到这样的结果:

a
b
end

但我明白这一点:

end
a
b

这是我的代码:

var a =  function(){
        return q.Promise(function(resolve, reject){
            resolve("a");
        });
    };

    var b =  function(){
        return q.Promise(function(resolve, reject){
            resolve("b");
        });
    };

    var c =  function(){
        return q.Promise(function(resolve, reject){
            resolve("c");
        });
    };

    var master =  q();

    master.then(function(){
        return a();
    })

    .then(function(res){
        console.error(res);
        return b();
    })

    .then(function(res){
        console.error(res);
            return c();
    });

    master.then(function(){
        console.error("end");
    });

如果我更改此部分:

master.then(function(){
        return a();
    })

到此:

master = master.then(function(){
        return a();
    })

代码工作正常,但我不知道为什么?这对我了解和理解这一点非常重要。有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:2)

您所看到的是链接和分支之间的区别,这是承诺控制流的不同形式。

当你这样做时:

master.then(function(){
    return a();
})

然后,后来:

master.then(function(){
    console.error("end");
});

您已将两个.then()处理程序挂钩到同一个承诺。这是分支。解析master()后,这些.then()处理程序中的每一个都将彼此独立地调用,并且每个处理程序都成为它们自己的独立链(因此原始链分支成为两个链)

链接就像:

master.then(function(){
    return a();
}).then(function(){
    console.error("end");
});

在链接的情况下,在.then()返回的任何承诺也被解决并且a()抛出或返回被拒绝的承诺第二个{a()时,将不会调用第二个.then()处理程序。 1}}处理程序在这里根本没有被调用。

在第一个示例的分支情况下,第二个.then()处理程序在第一个.then()处理程序之后立即调用,而不管a()返回什么。

然后你这样做:

master = master.then(function(){
    return a();
})

之前:

master.then(function(){
    console.error("end");
});

您手动链接它们,以便您有效地完成:

master.then(function(){
    return a();
}).then(function(){
    console.error("end");
});

请记住,每次调用.then()都会返回一个新的承诺。链接,如:

a().then(b).then(c)

在链中的每个步骤创建一个新的新承诺,并且除非处理程序返回的任何内容也被解析,否则新的承诺不会得到解决。

所以,当你做的时候:

master = master.then(function(){
    return a();
})

你正在抓住那个中间承诺(通过分配给master)并挂在它上面,这样你就可以把东西链接到它上面了。如果您这样做:

master.then(function(){
    return a();
})

然后,master.then()返回的承诺已完成,无法直接链接。

有关链接与分支的进一步说明,请参阅这些帖子:

Understanding javascript promises; stacks and chaining

Is there a difference between promise.then.then vs promise.then; promise.then

这是一个显示承诺分支的片段:



function log(str) {
    var d = document.createElement("div");
    d.textContent = str;
    document.body.appendChild(d);
}

function setDelay(t, msg) {
    return function() {
        return delay(t, msg);
    }
}

function delay(t, msg) {
    // if only one string argument, default t to 500ms
    if (typeof t === "string" && typeof msg === "undefined") {
        msg = t;
        t = 500;
    }
    return new Promise(function(resolve) {
        setTimeout(function() {
            log(msg);
            resolve(msg);
        }, t);
    });
}

var x = Promise.resolve().then(setDelay("One"))
	.then(setDelay("Two"))
	.then(function() {
    	log("Three");
	});

x.then(setDelay(500, "Four"))
    .then(setDelay(500, "Five"))
    .then(setDelay(500, "Six"));

x.then(setDelay(50, "Seven"))
    .then(setDelay(50, "Eight"))
    .then(setDelay(50, "Nine"));

x.then(setDelay(10, "Ten"))
    .then(setDelay(10, "Eleven"));




<强>解释

一,二,三连在一起,所有的分支都依赖于它们。然后,该链分成三个独立的分支。

Ten,Eleven分支首先执行,因为它有10ms的定时器。

然后,七,八,九分支下一个50ms定时器。

然后,四,五,六分支持续500ms定时器

注意:我故意这样做,所以分支计时器不重叠,但这不是承诺强制实施的,因为我选择的计时器值恰好就是这种情况。所有三个分支都是独立运行的,并且如果它们的活动具有重叠的时间,则可以交错。