前言
浏览器是单线程,自上向下执行任务,而为了避免阻塞卡死的现象,渲染进程内部会维护多个消息队列,比如延迟执行队列(Event Queue - 事件队列)和普通的消息队列。然后主线程采用一个for循环(就是Event Loop - 事件循环),不断地从这些任务队列中取出任务并执行任务。而这些任务(Event Task - 事件任务)又被细分为宏任务和微任务。
另外,我们需要注意的是宏任务和微任务都是异步。
macro-task 宏任务
- 什么是宏任务:可以直接理解是主线程的任务
- 特点:
- 宏任务的时间粒度大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合
- 每个宏任务都关联一个微任务队列
- 任务种类:
- 包括整体代码script
- setTimeout
- setInterval
- I/O
- UI 交互事件
- setImmediate(Node.js 环境)
micro-task 微任务
- 什么是微任务:就是一个需要异步执行的函数
- 特点:
- 微任务的时间粒度小
- 执行时机是在主函数执行结束之后,当前宏任务结束之前。简单讲,当宏任务和微任务都存在时,先执行微任务
- 任务种类:
- process.nextTick (node.js 独有)
- Promise
- MutaionObserver
- nextTick
- callback
- Object.observe
- MutationObserver
事件循环图谱
执行顺序:主线程(宏任务)=> 微任务 => 宏任务 => 主线程