从另一个承诺中解析外部承诺 — 交替执行顺序?



我注意到在解决一个承诺和另一个承诺时有一些有趣的行为:

const someTask = callback => {
new Promise(res => res())
.then(() => callback())
.then(() => console.log("A 1!"))
.then(() => console.log("A 2!"));
};
new Promise(res => someTask(res))
.then(() => console.log("B 1!"))
.then(() => console.log("B 2!"));

这输出:

B 1!
A 1!
B 2!
A 2!

我的想法是它会:

至少一次将
  1. 其中一个链排队,以便所有 A 的.then回调将首先运行,然后运行 B,反之亦然,但它们似乎来回交替,这令人费解。

  2. 在 B 之前
  3. 运行 A 的第一个日志语句,因为它在 B 之前解析。

我知道这两者都可能依赖于实现,并且我不应该在这里依赖执行顺序(在我的项目中,我只关心 A 在完成后解析 B(,但它让我对为什么会发生这种情况很感兴趣。这是原生承诺,蓝鸟产生相同的输出。

我将避免像EnqoeueJob这样的规范术语,以免更令人困惑

每当您.then(() => { ... })时,都会将微任务排队。微任务总是在只剩下平台代码时运行,所以"最后",并且总是在 I/O 之前运行。

在您的情况下:

  • 所有 promise 构造函数都同步运行 - 就像它们一直做的那样。
  • 您的then总是在新的微勾上运行。

这意味着在您的情况下:

  1. 第一个承诺构造函数同步运行,调用 someTask。
  2. someTask 创建一个承诺并同步实现它。
  3. 微滴答声过去了,then被调用,它实现了最初的承诺。
  4. 它的当时是预定的,也是原始承诺的当时
  5. 然后那些都安排然后,交替

这是因为微刻度只是在微任务队列的末尾安排。所以交替是"正确"的行为。

这不是执行定义的 - 尽管这是一个巧合,在建立承诺时是一个错误。您可以但不应该依赖该顺序。

最新更新