JavaScript事件循环及任务处理##
浏览器中 JavaScript 的执行流程和 Node.js 中的流程都是基于 事件循环 的。
理解事件循环的工作方式对于代码优化、性能优化很重要,有时对于正确的架构也很重要。
我们首先介绍事件循环工作方式的理论细节,然后介绍该知识的实际应用。
1. 事件循环
事件循环
的概念非常简单。它是一个在 JavaScript 引擎等待任务,执行任务和进入休眠状态等待更多任务这几个状态之间转换的无限循环。
引擎的一般算法:
1.当有任务时:从最先进入的任务开始执行。
2.休眠直到出现任务,然后转到第 1 步。
当我们浏览一个网页时就是上述这种形式。JavaScript 引擎大多数时候不执行任何操作,它仅在脚本/处理程序/事件激活时执行。
比如,我们操作网页的时候都会产生哪些任务
- 外部脚本加载完成时,任务就是执行脚本
- 用户移动鼠标时,任务就是派生出的mousemove事件和事件处理程序
- 当定时器setTimeout时间到达时,任务就是执行回调
- 当Promise.then响应时,任务就是执行回到函数
- 等等类似任务
当然,处理引擎不总是这么空闲能够及时处理这些任务,那有人就会问了,那这个情况该怎么办?
那当然是进行排队了,采用 先进先出
的原则进行排队,然后等待事件队列的处理,也就是开头那张图的处理机制,直至所有任务处理完成,处理引擎就会进入到休眠状态等待新的任务到来。
2. 宏观任务和微观任务(MACRO TASK AND MICRO TASK)
Js 中,有两类任务队列:宏任务队列(macro tasks)和微任务队列(micro tasks)。宏任务队列可以有多个,微任务队列只有一个。那么什么任务,会分到哪个队列呢?
- 宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.
- 微任务:process.nextTick, Promise, Object.observer, MutationObserver.
微任务始终先于宏任务执行。
宏任务和微任务的一些演示可以参考我这个文章 微任务和宏任务的区别及具体场景