在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();
})
代码工作正常,但我不知道为什么?这对我了解和理解这一点非常重要。有人可以向我解释一下吗?
答案 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定时器
注意:我故意这样做,所以分支计时器不重叠,但这不是承诺强制实施的,因为我选择的计时器值恰好就是这种情况。所有三个分支都是独立运行的,并且如果它们的活动具有重叠的时间,则可以交错。