我还在学习JavaScript Promise
,我遇到了一个我不明白的行为。
var o = $("#output");
var w = function(s) {
o.append(s + "<br />");
}
var p = Promise.resolve().then(function() {
w(0);
}).then(function() {
w(1);
});
p.then(function() {
w(2);
return new Promise(function(r) {
w(3);
r();
}).then(function() {
w(4);
});
}).then(function() {
w(5);
});
p.then(function() {
w(6);
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>
&#13;
我希望这些语句按顺序运行 - 也就是说,输出将是
0
1
2
3
4
5
6
相反,输出是
0
1
2
3
6
4
5
即使移除内部Promise
,也会产生与我相似的结果。在1
之前输出2
,但在6
之前输出5
。
有人可以向我解释一下吗?
我注意到的是,每次重新分配p
都会给我们预期的订单。
答案 0 :(得分:28)
你早期看到6
的原因是因为你没有链,你分支了。
当你致电p.then().then().then()
时,你会得到一系列承诺必须以正确的顺序执行。
但是,如果你打电话给p.then().then(); p.then()
,你就有2个承诺附加到p
- 基本上是创建一个分支,第二个分支将与第一个分支一起执行。
您可以通过确保将它们链接在一起p = p.then().then(); p.then();
仅供参考,除非你将它们重新组合在一起(例如Promise.all
),否则你几乎不想分支,或者故意创建一个“火与忘记”分支。
答案 1 :(得分:4)
r()做什么?
订购是不确定的,因为您正在接受相同的承诺 - &gt;这特指第二和第三链。
如果您正在执行以下操作,则可以保证订单:
var p = Promise.resolve().then(function() {
w(0);
}).then(function() {
w(1);
});
// Key difference, continuing the promise chain "correctly".
p = p.then(function() {
w(2);
return new Promise(function(r) {
w(3);
r();
}).then(function() {
w(4);
});
}).then(function() {
w(5);
});
p.then(function() {
w(6);
});
答案 2 :(得分:0)
为了清楚起见,让我们为示例中的每个承诺和功能起一个名字:
var pz = Promise.resolve();
function f0() { w(0); }
var p0 = pz.then(f0);
function f1() { w(1); }
var p1 = p0.then(f1); // p1 is 'p' in your example
function f2() {
w(2);
function f3(resolve_p3) {
w(3);
resolve_p3();
}
var p3 = new Promise(f3);
function f4() { w(4); }
var p4 = p3.then(f4);
return p4;
}
var p2 = p1.then(f2);
function f5() { w(5); }
var p5 = p2.then(f5);
function f6() { w(6); }
var p6 = p1.then(f6);
让我们一步一步来看看会发生什么。首先是顶层执行:
pz
已完成,因此pz.then(f0)
立即将f0
排队等待执行,其结果将解决p0
。f1
被安排为在p0
完成后排队,其结果将解决p1
。f2
被安排为在p1
完成后排队,其结果将解决p2
。f5
被安排为在p2
完成后排队,其结果将解决p5
。f6
被安排为在p1
完成后排队,其结果将解决p6
。然后将运行排队的作业(最初只是f0
):
f0
被执行:打印“ 0”。 p0
被满足,因此f1
被添加到队列中。f1
被执行:打印“ 1”。 p1
被满足,因此f2
和f6
被添加到队列(按该顺序)。这是至关重要的一点,因为这意味着f6
将在以后的任何作业排队之前执行。f2
被执行:打印“ 2”。f2
内部):new Promise
调用f3
,它显示“ 3”并满足p3
。f2
内部):由于已经完成了p3
,因此f4
被添加到队列中,其结果将解决p4
。f2
最终将p2
解析为p4
,这意味着一旦完成p4
,p2
也将得到满足。f6
被执行:打印“ 6”。 p6
得到满足。f4
被执行:打印“ 4”。 p4
成为现实。 p2
被满足,因此f5
被添加到队列中。f5
被执行:打印“ 5”。 p5
得到满足。