Promise.resolve().then 以后怎么执行呢?

How can Promise.resolve().then execute later?

使用原生 Javascript 承诺:

Promise.resolve(1).then(it => console.log(it))
console.log(2)

记录如下:

2
1

问题:怎么可能2先于1执行? JS 是事件驱动的,当原始调用者已经离开执行树时,执行给 then 的回调的事件是什么?引擎是否在这里进行某种幕后魔术?

JavaScript 维护称为调用堆栈的东西。这用于跟踪我们在脚本中的行踪。当您调用一个函数时,它会被添加到调用堆栈中,而当函数 returns/finishes 时,它会从调用堆栈中取出 removed/popped。将整个脚本也视为在其自己的“函数”中也很有帮助,因此,当您的脚本首次开始执行时,我们将“脚本”添加到调用堆栈中:

Stack:
- Script

当您的 Promise 解析时,它会执行其关联的 .then() 方法并将回调添加到称为微任务队列的东西中。使用此队列(连同宏任务队列)以便 JavaScript 可以管理异步事件。结果,一旦你 运行:

Promise.resolve(1).then(it => console.log(it))

你的 queues/stacks 的状态看起来像这样(注意,这是 Promise.resolve(1) 和 .then() 被 added/popped 关闭调用堆栈后的状态):

Stack:
- Script

Micro task queue:
- it => console.log(it)

微任务队列中的回调只有在添加到Stack后才会执行。这是通过使用事件循环实现的。只有当调用栈为空时,事件循环才会从微任务队列中拉出任务。目前,我们仍在 运行ning“脚本”,因此调用堆栈还不为空。

接下来,您会遇到 console.log(2),因为这是一个函数调用,它会被添加到调用堆栈中,一旦它 returns 就会弹出。这就是为什么您在控制台中首先看到 2 的原因,因为 Promise 的 .then() 回调尚未执行,因为它位于微任务队列中等待主脚本完成。主脚本完成后,“脚本”从堆栈中弹出:

Stack:
- (empty) <----------------<
                           | --- gets moved to the stack by the event-loop
Micro task queue:          |
- it => console.log(it) ---^

事件循环然后从微任务队列中移动任务,因为调用堆栈是空的。一旦任务移动到调用堆栈,它就会执行,运行第二个 console.log(it)。这就是为什么您在 2.

之后看到 1 在控制台中登录的原因