附加不同承诺链时 Javascript 承诺的执行顺序 [英] Execution order of Javascript promises when different promise chains attached

查看:47
本文介绍了附加不同承诺链时 Javascript 承诺的执行顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过创建一个 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 thens 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 调用 setTimeout API 对象被返回.然后它开始以相同的顺序注册从 1 到 5 的所有 then .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 thens 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆