javascript - Promise.resolve().then 稍后如何执行?

标签 javascript v8

使用原生 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)。这就是为什么您会在控制台中看到 12 之后登录。

关于javascript - Promise.resolve().then 稍后如何执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66730949/

相关文章:

google-apps-script - Google Apps Script V8 引擎是否支持 Promise?

javascript - 我应该在生成的代码中使用 "with"语句吗?

javascript - 减少 AngularJS 中评估的 ng-disabled 的事件触发器

javascript - Rails ActionCable/Turbolinks 聊天问题 : posting duplicate messages

node.js - 为什么 node.js 处理 setTimeout(func, 1.0) 不正确?

javascript - 独立运行 V8 Javascript 引擎

javascript - v8 对嵌套函数的优化效果如何?

Javascript 代码不工作

javascript - 很奇怪!调用 window.location 或 location.replace 会重定向到该页面,然后再次返回!

javascript - 如果类属性不改变,现代 JavaScript (V8) 是否会对类方法进行缓存?