# 九.事件环
前言
事件循环中的异步队列有两种:macro(宏任务)队列和 micro(微任务)队列
macro-task
:常见的有 setTimeout、setInterval、 setImmediate、script(整体代码)、 I/O 操作、UI 渲染等。micro-task
:常见的有 process.nextTick、Promise、MutationObserver 等。
# 1.Event Loop 过程
- 初始状态:调用栈空。micro 队列空,macro 队列里有且只有一个 script 脚本(整体代码)。
- 全局上下文(script 标签)被推入调用栈,同步代码执行。在执行的过程中,通过对一些接口的调用,可以产生新的 macro-task 与 micro-task,它们会分别被推入各自的任务队列里。同步代码执行完了,script 脚本会被移出 macro 队列,这个过程本质上是队列的 macro-task 的执行和出队的过程。
- 接着处理的是 micro-task。但需要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。因此,我们处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。
- 执行渲染操作,更新界面
- 检查是否存在 Web worker 任务,如果有,则对其进行处理
(上述过程循环往复,直到两个队列都清空)
# 2.渲染的时机
假如我想要在异步任务里进行 DOM 更新,我该把它包装成 micro 还是 macro 呢
setTimeout(task, 0) // macro:script --> micro --> render --> macro --> render
1
Promise.resolve().then(task) // micro:script --> micro --> render
1
对比发现,当我们需要在异步任务中实现 DOM 修改时,把它包装成 micro 任务是相对明智的选择
← 八.同步与异步