当Node.js运行以下代码时会发生什么?
setTimeout(() => console.log(1), 10)
Promise.resolve().then(() => console.log(2))
console.log(3)
如果您的答案与:
不同
3
2
1
也许您不完全了解JavaScript的执行顺序和事件循环的操作。
不用担心,我会尝试解释。
首先,如果您对什么有疑问:
- javascript
- ecmascript
- javascript Runtime
我建议您在继续之前阅读glossary。
现在,让我们解释一下此JavaScript代码执行的每个阶段发生的情况。
主线程
节点在单个线程中从上到下解释JavaScript文件。
运行settimeout()
主线程将解释第一个指令,将其添加到呼叫堆栈中,并将其从 call stack stack 。。
删除。 setTimeout
指令用于安排某些毫秒后的函数执行。
此功能是koude1库的一部分,该函数使用该函数创建计时器而无需阻止主 thread 。
启动计时器,主 thread 将从 call call stack stack 。。。
在间隔结束时,计时器将添加 settimeout 函数的回调 函数P>
运行Promise.resolve()。然后()
计时器 libuv 库等待10ms时, main thread 将解释文件的下一行。 P>
这次的说明是
Promise.resolve().then(() => console.log(2))
主 thread 将执行函数Promise.resolve()。然后()
Promise 是代表异步操作的完成或失败的对象。
通过无需任何参数调用resolve()函数,我们正在声明 promise , 都可以返回任何值,但这还可以。
目前,我们对的行为更感兴趣。
通过将 换句话说,我们说的是,一旦执行了 promise 的resolve()方法,节点应执行我们的 console.log(2)指令。 但是,这并不是它的工作方式。 每个 promise 回调立即发送到一个特殊队列,称为 Micro Tasks Queue queue 。 这是脚本执行的当前状态: 到目前为止发生的一切肯定花了不到10毫秒的时间,这就是为什么计时器尚未将 但是,通过使用 libuv ,主线程可以以非阻滞方式继续正常工作。 好吧,您可能想知道: 在整个过程中,通过文件中的每行解释,事件循环执行了一个非常重要的,尽管重复的功能。 您可以看到,答案总是: no! 在执行此脚本期间,任何时间都没有 call stack 空,所以我们的朋友事件循环将继续等待。 现在,主线程解释文件的最后指令。 这是一个简单的指令,在 console 上显示一个值,其结果是: ,第一次, call stack 是空! 现在,事件循环的最期待的时刻,它有能力行动的时刻! 当 call stack stack 为空! 在每个循环中,它将: 主线程在主要上下文中执行所有指令。 现在,继续执行示例代码: 当调用stack 变为空时,这意味着主线程没有执行任何内容。 然后,事件循环消耗从 micro任务队列中的所有任务,并将它们添加到 call stack stack 。 现在,调用stack 再次变为空。 然后,事件循环在 Micro Tasks中寻找更多任务队列。 当它是空的,它在 Micro Task Queue 中完成工作,并开始消耗宏观任务队列Queue 。
现在,假设10毫秒间隔已经传递,并且 timer 已将控制台插入了台。 >事件循环() => console.log(2)
作为我们的 Promise 的回调,我们告诉节点,一旦成功完成 Promise ,请立即执行此代码。
回顾
console.log(1)
的指示添加到宏观任务队列的原因。
事件循环
清空调用堆栈
3
事件循环
微型任务
console.log(2) // Writes 2 to the console
宏任务
然后,主线程消耗 call stack stack 的最后一个指令并执行它。
console.log(1) // Writes 1 to the console
重要的一点:如果微观任务队列中仍然有指示,则将处理这些指示。但是,由于所有内容都是空的,因此程序执行将朝着末尾。
这就是为什么代码:
setTimeout(() => console.log(1), 10)
Promise.resolve().then(() => console.log(2))
console.log(3)
将导致:
3
2
1
我们已经到达末尾-Arlindo Cruz
现在您了解了JavaScript场景后面会发生什么。 事件循环管理 micro 和 macro 任务的队列,因此,确保在主要背景下和谐地执行异步指令线程。
了解其工作原理有助于我们编写更有效的代码并更好地预测应用程序的行为。
下次您编写JavaScript代码时,希望您还记得 event loop 的一切发生的一切
稍后再见! 这是一种支持多个编程范式的高级,动态,解释的编程语言(功能,命令,面向对象)。 这是您想做的事情与计算机执行的操作之间的“媒介”。 这是一个set of rules,定义了JavaScript的工作方式,它定义了语言标准(语法,数据类型,控制结构和操作员),而JavaScript是这些标准的实现。 如果您想更好地了解,请阅读this article 是引擎执行JavaScript代码。 编写JavaScript代码时,您可以编写指令(遵循由ecmascript定义的规则),但是要执行这些说明,您需要 Run> Runtime 。 好像JavaScript是食谱,运行时是执行食谱的厨师。 Node,V8和SpiderMonkey是世界上最著名的Javascript Runtimes 。
词汇表
JavaScript
Ecmascript
JavaScript运行时