承诺订单调用
Promise order invocation
给定以下代码
Promise.resolve().then(() => {
console.log(0);
return Promise.resolve(4);
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
我认为这会给出 0 4 1 2 3 5 6
但输出是 0 1 2 3 4 5 6
。
任何人都可以评论为什么会这样吗?
首先,这是两个独立的承诺链。在现实世界的异步编码中,这两个独立链中不同步骤之间的时序是完全不相连的。 所以,这根本不是现实世界的问题。这是一种纯粹的学术练习或一种求知欲。
在现实世界的编码中,如果您关心这两个链中操作之间的相对顺序,您将不会有两个独立的承诺链。相反,您会将它们 link 放入一个链中,您可以在其中控制顺序。
哦,甚至 Javascript/promise 规范有时也会发生变化,这些变化也可能会影响这一详细程度。几年前,规范对 await
的工作方式进行了更改,以提高 promise 性能,这确实影响了这些类型的测试场景(使用 await
时)的详细计时。
也就是说,唯一真正的问题是为什么 4
的输出会出现在它所在的位置。我们最初可以通过更改代码来检查问题,使第一个 .then()
处理程序不是 return Promise.resolve(4)
,而是只执行 return 4;
。当我们这样做时,这就是您得到的:
Promise.resolve().then(() => {
console.log(0);
return 4;
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
然后,您得到输出:
0
1
4
2
3
5
6
好的,现在问题简化为为什么 return Promise.resolve(4)
导致 4
在顺序上比 return 4;
延迟两个点?
这与 return 来自 .then()
处理程序的承诺与 return 来自普通值的区别有关。当您 return 一个值时,链中的下一个承诺可以立即用该值解析,并且附加到该承诺的后续 .then()
处理程序可以立即添加到承诺作业队列中。
但是,当您 return 一个 promise 时,链中的下一个 promise 必须通过向其添加 .then()
处理程序并等待它来监控 returned promise得到解决。尽管它已经在技术上得到解决,但从承诺中获得价值的唯一方法仍然是通过附加一个 .then()
处理程序(或使用 await
),这样仍然有即将发生。这允许其他事情提前进入承诺作业队列。
因此,您可以立即看到 4
输出会延迟一些。这个延迟允许接下来输出 2
。然后,父 promise 附加到 Promise.resolve(4)
的 .then()
处理程序开始执行,所以现在第一个 promise 链开始进入下一步。为此,它会在承诺作业队列中添加下一个 .then()
处理程序作业。但是,这不是队列中的下一项工作。队列中的下一个作业在输出 2
后从第二条链放在那里。所以,我们接下来得到那个工作,输出 3
来了,最后 4
开始了。
因此,通过 return Promise.resolve(4)
,我们不仅将此链延迟了一个周期,而且还允许第二个 promise 链中的下一个事件在第一个链 - 因此基本上使我们在作业队列中占据两个位置。
因此,return Promise.resolve(4)
和 return 4
之间的区别在于,由于添加 .then()
的时间,随后的 .then()
处理程序在此处相对顺序下降了两个位置承诺作业队列的处理程序。
给定以下代码
Promise.resolve().then(() => {
console.log(0);
return Promise.resolve(4);
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
我认为这会给出 0 4 1 2 3 5 6
但输出是 0 1 2 3 4 5 6
。
任何人都可以评论为什么会这样吗?
首先,这是两个独立的承诺链。在现实世界的异步编码中,这两个独立链中不同步骤之间的时序是完全不相连的。 所以,这根本不是现实世界的问题。这是一种纯粹的学术练习或一种求知欲。
在现实世界的编码中,如果您关心这两个链中操作之间的相对顺序,您将不会有两个独立的承诺链。相反,您会将它们 link 放入一个链中,您可以在其中控制顺序。
哦,甚至 Javascript/promise 规范有时也会发生变化,这些变化也可能会影响这一详细程度。几年前,规范对 await
的工作方式进行了更改,以提高 promise 性能,这确实影响了这些类型的测试场景(使用 await
时)的详细计时。
也就是说,唯一真正的问题是为什么 4
的输出会出现在它所在的位置。我们最初可以通过更改代码来检查问题,使第一个 .then()
处理程序不是 return Promise.resolve(4)
,而是只执行 return 4;
。当我们这样做时,这就是您得到的:
Promise.resolve().then(() => {
console.log(0);
return 4;
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
然后,您得到输出:
0
1
4
2
3
5
6
好的,现在问题简化为为什么 return Promise.resolve(4)
导致 4
在顺序上比 return 4;
延迟两个点?
这与 return 来自 .then()
处理程序的承诺与 return 来自普通值的区别有关。当您 return 一个值时,链中的下一个承诺可以立即用该值解析,并且附加到该承诺的后续 .then()
处理程序可以立即添加到承诺作业队列中。
但是,当您 return 一个 promise 时,链中的下一个 promise 必须通过向其添加 .then()
处理程序并等待它来监控 returned promise得到解决。尽管它已经在技术上得到解决,但从承诺中获得价值的唯一方法仍然是通过附加一个 .then()
处理程序(或使用 await
),这样仍然有即将发生。这允许其他事情提前进入承诺作业队列。
因此,您可以立即看到 4
输出会延迟一些。这个延迟允许接下来输出 2
。然后,父 promise 附加到 Promise.resolve(4)
的 .then()
处理程序开始执行,所以现在第一个 promise 链开始进入下一步。为此,它会在承诺作业队列中添加下一个 .then()
处理程序作业。但是,这不是队列中的下一项工作。队列中的下一个作业在输出 2
后从第二条链放在那里。所以,我们接下来得到那个工作,输出 3
来了,最后 4
开始了。
因此,通过 return Promise.resolve(4)
,我们不仅将此链延迟了一个周期,而且还允许第二个 promise 链中的下一个事件在第一个链 - 因此基本上使我们在作业队列中占据两个位置。
因此,return Promise.resolve(4)
和 return 4
之间的区别在于,由于添加 .then()
的时间,随后的 .then()
处理程序在此处相对顺序下降了两个位置承诺作业队列的处理程序。