JavaScript的宏任务与微任务
一、同步任务与异步任务
首先,我们需要搞清楚同步任务和异步任务的概念以及工作原理。
同步任务
同步任务指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
异步任务
异步任务指的是刚开始不进入主线程,当主线程的任务执行完了之后再调用异步任务,异步任务任务才会进入主线程执行。(setTimeout, setInterval,promise,process.NextTick)
工作原理
- 同步和异步任务分别进入不同的执行“场所”,同步的进入主线程,异步的进入 Event Table 并注册函数。
- 当指定的事情完成时,Event Table 会将这个函数移入 Event Queue。
- 主线程内的任务执行完毕为空,会去 Event Queue 读取对应的函数,进入主线程执行。
- 上述过程会不断重复,也就是常说的 Event Loop(事件循环)。
二、宏任务与微任务
除了广义的同步任务和异步任务,我们对任务有更精细的定义。
宏任务(macro-task)
包括整体代码script,setTimeout,setInterval。
微任务(micro-task)
Promise,process.nextTick。
注意:不同类型的任务会进入对应的 Event Queue,也就是说微任务会进入微任务的 Event Queue,宏任务会进入宏任务的 Event Queue。比如setTimeout
和setInterval
会进入相同的 Event Queue。
工作原理
如下示例:
1 | setTimeout(function() { |
- 这段代码作为宏任务,进入主线程。
- 先遇到
setTimeout
,为异步的宏任务,那么将其回调函数注册后分发到宏任务Event Queue。 - 接下来遇到了
Promise
,new Promise
立即执行,then
函数为异步的微任务,分发到微任务 Event Queue。 - 遇到
console.log()
,立即执行。 - 整体代码 script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了
then
在微任务 Event Queue里面,执行。 - ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务 Event Queue 开始。我们发现了宏任务 Event Queue中
setTimeout
对应的回调函数,立即执行。 - 结束。