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
在控制台中登录的原因
使用原生 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
在控制台中登录的原因