使用原生 Javascript Promise:
Promise.resolve(1).then(it => console.log(it))
console.log(2)
已记录:
2
1
问题:如何2
可以在1
之前执行? JS 是事件驱动的,当原始调用者已经离开执行树时,执行给 then
的回调的事件是什么?引擎在这里做了某种幕后魔法吗?
最佳答案
JavaScript 维护着一种称为调用堆栈的东西。这用于跟踪我们在脚本中的行踪。当您调用一个函数时,它会被添加到调用堆栈中,当函数返回/完成时,它会被从调用堆栈中删除/弹出。将整个脚本视为位于其自己的“函数”中也很有帮助,因此,当您的脚本首次开始执行时,我们将“脚本”添加到调用堆栈中:
Stack:
- Script
当您的 Promise 解析时,它会执行关联的 .then()
方法,并将回调添加到称为微任务队列的东西中。使用此队列(以及宏任务队列)以便 JavaScript 可以管理异步事件。结果,一旦你运行:
Promise.resolve(1).then(it => console.log(it))
队列/堆栈的状态如下所示(注意,这是 Promise.resolve(1) 和 .then() 添加到调用堆栈/从调用堆栈中弹出后的状态):
Stack:
- Script
Micro task queue:
- it => console.log(it)
微任务队列中的回调只有在添加到堆栈后才会执行。这是通过使用事件循环来实现的。仅当调用堆栈为空时,事件循环才会将任务从微任务队列中拉出。目前,我们仍在运行“脚本”,因此调用堆栈尚未为空。
接下来,您会遇到 console.log(2)
,因为这是一个函数调用,它会被添加到调用堆栈中,一旦返回,它就会被弹出。这就是为什么您在控制台中看到 2
首先出现的原因,因为 Promise 的 .then()
回调尚未执行,因为它位于微任务中排队等待主脚本完成。主脚本完成后,“脚本”就会从堆栈中弹出:
Stack:
- (empty) <----------------<
| --- gets moved to the stack by the event-loop
Micro task queue: |
- it => console.log(it) ---^
由于调用堆栈为空,事件循环随后将任务从微任务队列中移出。一旦任务被移动到调用堆栈,它就会执行,运行第二个 console.log(it)
。这就是为什么您会在控制台中看到 1
在 2
之后登录。
关于javascript - Promise.resolve().then 稍后如何执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66730949/