附加不同 Promise 链时 JavaScript Promise 的执行顺序

s1n*_*7ax 2 javascript node.js promise

我想promise通过创建promise并传递它并让其他人将 附加then到它来检查对象的可移植性。输出与我的预期相去甚远,我不明白它是如何执行的。

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'));
Run Code Online (Sandbox Code Playgroud)

输出:

1
2
4
3
5
Run Code Online (Sandbox Code Playgroud)

我调试了代码,这是我观察到的。调用通过传递回调来wait(5000)调用Promise调用setTimeoutAPI的构造函数res,并 Promise返回对象。then然后它开始以相同的顺序注册从 1 到 5 的所有s。5 秒后,它resPromise调用承诺链的对象中调用。

在我看来,thenAPI 将所有的添加callbacks到一个数组或类似的东西中,从 1 到 5,一旦res被调用,它就会开始callbacks从数组中一一调用(先进先出),这应该会产生日志1 2 3 4 5not 1 2 4 3 5

为了将它们注册到 main ,如何不执行此操作promise

jfr*_*d00 5

首先,当你这样做时:

promise.then(...).then(...)
Run Code Online (Sandbox Code Playgroud)

这会附加一个.then()处理程序promise,第二个处理程序.then()会附加到第一个处理程序返回的新承诺.then()

因此,当promise解析时,第一个.then()被安排在事件循环的下一个周期触发。然后,仅当第一个.then()完成时,它才会安排第二个.then()在事件循环的下一个刻度上触发(它不会在事件循环的此刻度上运行)。

当你这样做时:

promise
  .then(() => console.log('2'))
  .then(() => console.log('3'));

promise
  .then(() => console.log('4'))
  .then(() => console.log('5'));
Run Code Online (Sandbox Code Playgroud)

然后,当promise解析时,then(2)以及直接附加的这段代码中then(4)仅有的两个处理程序被安排在事件循环的下一个标记上运行。在下一个滴答声中,首先运行,然后运行。由于它们都附加到相同的 Promise,因此它们以 FIFO 方式运行,第一个附加的首先运行。运行时,它计划在事件循环的下一个时钟周期运行,而运行时,它计划在事件循环的下一个时钟周期运行。.then()promisethen(2)then(4)then(2)then(3)then(4)then(5)

因此,在 和then(2)then(4)运行之后,在事件循环的下一个滴答声中,您将看到then(3)then(5)运行,这解释了您在控制台中看到的顺序:

1
2
4
3
5
Run Code Online (Sandbox Code Playgroud)

我想您对首先运行并不感到惊讶then(1),所以我没有将其添加到解释中。

为了将它们注册到主要承诺中,这是如何不执行的?

.then()直接连接的三个处理程序promise按照它们连接的顺序运行。显然让您感到困惑的是,链接的.then()处理程序不是直接附加到promise,而是附加到返回的新承诺promise.then()

.then()返回一个新的承诺,因为它可能不会立即解决。如果回调本身.then()返回一个 Promise,那么返回的 Promise.then()不会立即解析。它必须等到回调返回的承诺.then()也解决。

在我看来,API 将所有回调添加到一个数组或类似的东西中,从 1 到 5,一旦调用 res,它就会开始从数组中一一调用回调(先进先出),这应该会生成日志 1 2 3 4 5 而不是1 2 4 3 5。

好吧:1、2 和 4 确实被添加到.then()promise对象的同一个处理程序回调数组中。但是,如上所述,3 和 5 是由它们.then()所链接到的不同 Promise 创建的。所以,1、2、4都是按先进先出执行的。但 3 和 5 被延迟到事件循环的后续滴答。

  • @s1n7ax - 简单的例子:`Promise.resolve(1).then(x => console.log(x)); console.log(2);` 将显示为 `2`,然后显示为 `1`,因为 `.then()` 被安排在事件循环的下一个周期,但 `console.log(2)` 在此运行事件循环的刻度。 (2认同)