附加不同承诺链时 Javascript 承诺的执行顺序 [英] Execution order of Javascript promises when different promise chains attached
问题描述
我想通过创建一个 promise
并传递它并让其他人将 then
附加到它来检查 promise
对象的可移植性.输出与我预期的相差甚远,我不明白它是如何执行的.
I wanted to check the portability of a promise
object by creating an promise
and passing it around and let others attach then
s to it. The output is far from what I expected and I don't understand how it executed.
const wait = time => {
return new Promise((res, rej) => {
setTimeout(res, time);
});
};
const promise = wait(5000)
.then(() => console.log('1'));
promise
.then(() => console.log('2'))
.then(() => console.log('3'));
promise
.then(() => console.log('4'))
.then(() => console.log('5'));
输出:
1
2
4
3
5
我调试了代码,这是我观察到的.调用 wait(5000)
调用 Promise
的构造函数,通过传递 res
回调和 Promise 调用
对象被返回.然后它开始以相同的顺序注册从 1 到 5 的所有 setTimeout
APIthen
.5 秒后,它从调用承诺链的 Promise
对象调用 res
.
I debug the code and here is what I observed. calling wait(5000)
invokes constructor of Promise
that calls setTimeout
API by passing res
callback and Promise
object is returned back. then it starts registering all the then
s from 1 to 5 in the same order. After 5 seconds it calls res
from Promise
object which invokes the promise chains.
在我看来,then
API 将所有 callbacks
添加到数组或类似的东西中,从 1 到 5,一旦 res
是调用它开始从数组中一一调用 callbacks
(FIFO) 应该产生日志 1 2 3 4 5
而不是 1 2 4 3 5
.
In my mind, then
API adds all the callbacks
to an array or something like that, from 1 to 5 and once res
is called it starts calling callbacks
from the array one by one (FIFO) which should produces logs 1 2 3 4 5
not 1 2 4 3 5
.
为了将它们注册到主promise
,如何不执行此操作?
How is this not executed in order they are being registered to the main promise
?
推荐答案
首先,当你这样做时:
promise.then(...).then(...)
这将一个 .then()
处理程序附加到 promise
和第二个 .then()
附加到一个新的承诺,第一个.then()
返回.
That attaches one .then()
handler to promise
and the second .then()
is attached to a new promise that the first .then()
returns.
因此,当 promise
解析时,第一个 .then()
被安排在事件循环的下一个滴答上触发.然后,只有当第一个 .then()
完成时,它才会安排第二个 .then()
在事件循环的下一个滴答上触发(它不会继续运行)事件循环的这个滴答声).
So, when promise
resolves, the first .then()
is scheduled to fire on the next tick of the event loop. Then, only when the first .then()
finishes, it schedules the second .then()
to fire on the next tick of the event loop (it does not run on this tick of the event loop).
当你这样做时:
promise
.then(() => console.log('2'))
.then(() => console.log('3'));
promise
.then(() => console.log('4'))
.then(() => console.log('5'));
然后,当 promise
解析时,then(2)
和 then(4)
是仅有的两个 .then()
这段代码中直接附加到 promise
的处理程序被安排在事件循环的下一个滴答上运行.在下一个滴答声中,首先 then(2)
运行,然后 then(4)
运行.由于它们都附加到同一个 Promise,因此它们以 FIFO 方式运行,第一个被附加的首先运行.当 then(2)
运行时,它安排 then(3)
在事件循环的下一个滴答上运行,当 then(4)
运行,它安排 then(5)
在事件循环的下一个滴答上运行.
And, then when promise
resolves, then(2)
and then(4)
which are the only two .then()
handlers in this piece of code directly attached to promise
are scheduled to run on the next tick of the event loop. Upon that next tick, first then(2)
runs and then then(4)
runs. Since they were both attached to the same promise, they run in a FIFO manner, the first one to be attached runs first. When then(2)
runs, it schedules then(3)
to run on the next tick of the event loop and when then(4)
runs, it schedules then(5)
to run on the next tick of the event loop.
因此,在 then(2)
和 then(4)
都运行后,在事件循环的下一个滴答声中,您将看到 then(3)
和 then(5)
运行,这解释了您在控制台中看到的排序:
So, after both then(2)
and then(4)
have run, upon the next tick of the event loop, you will see then(3)
and then(5)
run and that explains the sequencing you see in the console of:
1
2
4
3
5
<小时>
我想您不会对 then(1)
首先运行感到惊讶,所以我没有将其添加到解释中.
I presume you're not surprised that then(1)
runs first so I didn't add that to the explanation.
为了将它们注册到主要承诺,如何不执行此操作?
How is this not executed in order they are being registered to the main promise?
直接附加到 promise
的三个 .then()
处理程序确实按照它们附加的顺序运行.显然让您感到困惑的是,链接的 .then()
处理程序没有直接附加到 promise
,而是附加到 promise.then()
的新承诺代码>返回.
The three .then()
handlers attached directly to promise
do run in the order they were attached. What is apparently confusing you is that the chained .then()
handlers are not attached directly to promise
, but to new promises that promise.then()
returns.
.then()
返回一个新的 promise,因为它可能不会立即解析.如果 .then()
内部的回调本身返回一个承诺,那么 .then()
返回的承诺不会立即解决.它必须等到 .then()
回调返回的承诺也解决.
.then()
returns a new promise because it may not resolve immediately. If the callback inside of .then()
itself returns a promise, then the promise that .then()
returns does not immediately resolved. It has to wait until the promise that the .then()
callback returned also resolves.
在我看来,然后 API 将所有回调添加到一个数组或类似的东西中,从 1 到 5,一旦 res 被调用,它就会开始从数组中一一调用回调(FIFO),这应该会产生日志 1 2 34 5 不是 1 2 4 3 5.
In my mind, then API adds all the callbacks to an array or something like that, from 1 to 5 and once res is called it starts calling callbacks from the array one by one (FIFO) which should produces logs 1 2 3 4 5 not 1 2 4 3 5.
好吧:1、2 和 4 确实被添加到 promise
对象的同一个 .then()
处理程序回调数组中.但是,如上所述,3 和 5 是在由 .then()
创建的单独承诺上,它们链接到.因此,1、2 和 4 执行 FIFO.但是 3 和 5 被延迟到事件循环的后续滴答.
Well: 1, 2 and 4 are indeed added to the same array of .then()
handler callbacks for the promise
object. But, as explained above, 3 and 5 are on separate promises that were created by the .then()
they are chained to. So, 1, 2 and 4 are executed FIFO. But 3 and 5 are delayed to a subsequent tick of the event loop.
这篇关于附加不同承诺链时 Javascript 承诺的执行顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!