提问人:Won Jin Kim 提问时间:6/26/2023 最后编辑:trincotWon Jin Kim 更新时间:6/26/2023 访问量:55
根据返回类型 [duplicate] 的 promise 执行顺序
The execution order of the promise according to the return type [duplicate]
问:
我想知道执行顺序因回调中返回的内容而异的原因:then
var a = Promise.resolve();
var b = a.then(function a_then() {
console.log(1);
var c = Promise.resolve();
var d = c.then(function c_then() {
console.log(2);
});
var e = d.then(function d_then() {
console.log(3);
});
console.log(4);
return c; // <--- this influences the output order
});
var f = b.then(function b_then() {
console.log(5);
var g = Promise.resolve();
var h = g.then(function g_then() {
console.log(6);
});
var i = h.then(function h_then() {
console.log(7);
});
console.log(8);
});
console.log(9);
如果没有那个(所以返回),输出顺序是:9,1,4,2,5,8,3,6,7,这个顺序被解释为我上一个问题的答案。return c
undefined
但是添加它会将输出顺序更改为 9,1,4,2,3,5,8,6,7。return c
为什么现在输出值 3 在值 5 和 8 之前?为什么事件的顺序是这样的?
注意:返回 或 时,输出也会发生类似的变化。d
e
如果您能使用用作我上一个问题答案的表格来解释它,那就太好了:
任务 | 行动 | 一个 | b | c | d | e | f | g | h | 我 | PromiseJob 队列 |
---|---|---|---|---|---|---|---|---|---|---|---|
脚本 | a = Promise.resolve() |
F | - | - | - | - | - | - | - | - | |
脚本 | b = a.then(a_then) |
F | ? | - | - | - | - | - | - | - | a_then |
脚本 | f = b.then(b_then) |
F | ? | - | - | - | ? | - | - | - | a_then |
脚本 | console.log(9) |
F | ? | - | - | - | ? | - | - | - | a_then |
主机 | 出列a_then |
F | ? | - | - | - | ? | - | - | - | |
a_then |
console.log(1) |
F | ? | - | - | - | ? | - | - | - | |
a_then |
c = Promise.resolve() |
F | ? | F | - | - | ? | - | - | - | |
a_then |
d = c.then(c_then) |
F | ? | F | ? | - | ? | - | - | - | c_then |
a_then |
e = d.then(d_then) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
console.log(4) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
返回解析b |
F | F | F | ? | ? | ? | - | - | - | c_then 、b_then |
主机 | 出列c_then |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
console.log(2) |
F | F | F | ? | ? | ? | - | - | - | b_then |
c_then |
返回解析d |
F | F | F | F | ? | ? | - | - | - | b_then 、d_then |
主机 | 出列b_then |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
console.log(5) |
F | F | F | F | ? | ? | - | - | - | d_then |
b_then |
g = Promise.resolve() |
F | F | F | F | ? | ? | F | - | - | d_then |
b_then |
h = g.then(g_then) |
F | F | F | F | ? | ? | F | ? | - | d_then 、g_then |
b_then |
i = h.then(h_then) |
F | F | F | F | ? | ? | F | ? | ? | d_then ,g_then |
b_then |
console.log(8) |
F | F | F | F | ? | ? | F | ? | ? | d_then ,g_then |
b_then |
返回解析f |
F | F | F | F | ? | F | F | ? | ? | d_then ,g_then |
主机 | 出列d_then |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
console.log(3) |
F | F | F | F | ? | F | F | ? | ? | g_then |
d_then |
返回解析e |
F | F | F | F | F | F | F | ? | ? | g_then |
主机 | 出列g_then |
F | F | F | F | F | F | F | ? | ? | |
g_then |
console.log(6) |
F | F | F | F | F | F | F | ? | ? | |
g_then |
返回解析h |
F | F | F | F | F | F | F | F | ? | h.then |
主机 | 出列h_then |
F | F | F | F | F | F | F | F | ? | |
h_then |
console.log(7) |
F | F | F | F | F | F | F | F | ? | |
h_then |
返回解析i |
F | F | F | F | F | F | F | F | F | |
主机 | 队列为空 | F | F | F | F | F | F | F | F | F |
答:
当满足时,将执行回调。该回调的返回值决定了解析方式。如果该回调返回一个 promise(如),则 promise 的一个核心特征就会发挥作用:promise 不会简单地用返回的 promise 对象来履行,而是会保持待处理状态并“锁定”到返回的 promise 上:promise 的结算方式将决定 will settle 的方式 -- 的命运被锁定在 的 上。a
a_then
b
then
c
b
c
b
b
c
调用的 Promise 内部实现通过检查返回的值来实现此目的。它检测到这个返回的值是一个 thenable(它有一个方法),并且实际上会计划调用该方法(在本例中),因为这是了解该 thenable 的稳定状态的唯一方法(在本例中)。它会将自己的(内部)回调传递给该方法。a_then
then
then
c.then
c
then
这是一个回调,它不是 JS 代码的一部分 -- 它由 Promise 实现提供(请参阅 Promise 解析函数步骤 13 上的 ECMAScript 规范)。此外,此调用将异步发生(请参阅同一规范中的步骤 14)。我们可以想象异步作业看起来像这样(简化):c.then
function lockin_b(c) {
c.then(function fulfill_b(value) {
_fulfill(value)
});
}
...其中是可以解决的内部功能。_fulfill
b
因此,总而言之,此锁定方案中涉及两个额外的异步作业:
- 由 Promise 内部的异步调用,以便锁定到
c.then
b
c
- 传递给 when 的回调的异步调用已解析。
c.then
c
这意味着它将比省略的时间晚,因此输出 5 和 8 的回调也将稍后执行。b
return c
b_then
下面是在执行该代码期间发生的一系列事件。
- 第一列表示正在执行的内容(主脚本、从事件循环启动的函数或从 PromiseJob 队列中取消项目排队的主机)
- 第二列包含正在计算的当前表达式/语句
- 表示具有该名称的 promise 状态的列:待处理、已实现和已解决但尚未结算(即锁定)。
a
i
?
F
R
- 最后一列描绘了由主机管理的 PromiseJob 队列中存在的内容
任务 | 行动 | 一个 | b | c | d | e | f | g | h | 我 | PromiseJob 队列 |
---|---|---|---|---|---|---|---|---|---|---|---|
脚本 | a = Promise.resolve() |
F | - | - | - | - | - | - | - | - | |
脚本 | b = a.then(a_then) |
F | ? | - | - | - | - | - | - | - | a_then |
脚本 | f = b.then(b_then) |
F | ? | - | - | - | ? | - | - | - | a_then |
脚本 | console.log(9) |
F | ? | - | - | - | ? | - | - | - | a_then |
主机 | 出列a_then |
F | ? | - | - | - | ? | - | - | - | |
a_then |
console.log(1) |
F | ? | - | - | - | ? | - | - | - | |
a_then |
c = Promise.resolve() |
F | ? | F | - | - | ? | - | - | - | |
a_then |
d = c.then(c_then) |
F | ? | F | ? | - | ? | - | - | - | c_then |
a_then |
e = d.then(d_then) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
console.log(4) |
F | ? | F | ? | ? | ? | - | - | - | c_then |
a_then |
return c 解决b |
F | R | F | ? | ? | ? | - | - | - | c_then 、lockin_b |
主机 | 出列c_then |
F | R | F | ? | ? | ? | - | - | - | lockin_b |
c_then |
console.log(2) |
F | R | F | ? | ? | ? | - | - | - | lockin_b |
c_then |
返回解析d |
F | R | F | F | ? | ? | - | - | - | lockin_b 、d_then |
主机 | 出列lockin_b |
F | R | F | F | ? | ? | - | - | - | d_then |
lockin_b |
c.then(fulfill_b) |
F | R | F | F | ? | ? | - | - | - | d_then 、fulfill_b |
lockin_b |
返回 | F | R | F | F | ? | ? | - | - | - | d_then ,fulfill_b |
主机 | 出列d_then |
F | R | F | F | ? | ? | - | - | - | fulfill_b |
d_then |
console.log(3) |
F | R | F | F | ? | ? | - | - | - | fulfill_b |
d_then |
返回解析e |
F | R | F | F | F | ? | - | - | - | fulfill_b |
主机 | 出列fulfull_b |
F | R | F | F | F | ? | - | - | - | |
fulfull_b |
_fulfill |
F | F | F | F | F | ? | - | - | - | b_then |
fulfull_b |
返回 | F | F | F | F | F | ? | - | - | - | b_then |
主机 | 出列b_then |
F | F | F | F | F | ? | - | - | - | |
b_then |
console.log(5) |
F | F | F | F | F | ? | - | - | - | |
b_then |
g = Promise.resolve() |
F | F | F | F | F | ? | F | - | - | |
b_then |
h = g.then(g_then) |
F | F | F | F | F | ? | F | ? | - | g_then |
b_then |
i = h.then(h_then) |
F | F | F | F | F | ? | F | ? | ? | g_then |
b_then |
console.log(8) |
F | F | F | F | F | ? | F | ? | ? | g_then |
b_then |
返回解析f |
F | F | F | F | F | F | F | ? | ? | g_then |
主机 | 出列g_then |
F | F | F | F | F | F | F | ? | ? | |
g_then |
console.log(6) |
F | F | F | F | F | F | F | ? | ? | |
g_then |
返回解析h |
F | F | F | F | F | F | F | F | ? | h.then |
主机 | 出列h_then |
F | F | F | F | F | F | F | F | ? | |
h_then |
console.log(7) |
F | F | F | F | F | F | F | F | ? | |
h_then |
返回解析i |
F | F | F | F | F | F | F | F | F | |
主机 | 队列为空 | F | F | F | F | F | F | F | F | F |
当函数中的语句返回不同的承诺时,可以进行类似的分析。这是同样的原则。return
b_then
评论
c
return c