前段时间我对于浏览器Event loop中的MacroTask和MicroTask哪个先执行有所困惑,苦于搜索也没有发现很明确的答案,于是决定深入探索浏览器Event loop,现有所愚见,想与大家分享,希望能帮助到那些还在爬坑的人。
1.什么是Event loop?
developer.mozilla.org给出的解释是这样的:
一个 JavaScript 运行时包含了一个待处理的消息队列。每一个消息都关联着一个用以处理这个消息的函数。
在事件循环期间的某个时刻,运行时从最先进入队列的消息开始处理队列中的消息。
大致可以理解为Event loop用来处理JavaScript事件执行的先后顺序。浏览器端Event loop中的异步队列有两种:MacroTask队列和 MicroTask队列。它们分别包括:
2.关于MacroTask和MicroTask。
MicroTask: process.nextTick ,promise ,MutationObserver,其中 process.nextTick 为 Node 独有。
MacroTask: script(整体代码),setTimeout ,setInterval ,setImmediate ,I/O ,UI rendering。
浏览器会不断从task队列中按顺序取task执行。
大体情况如下:
每执行完一个Macrotask都会检查microtask队列是否为空,如果不为空则会一次性执行完所有microtask。
3.同步事件和异步事件怎么处理?
一开始执行栈空,micro 队列空,macro 队列里有且只有一个 script 脚本(整体代码)。然后全局上下文(script 标签)被推入执行栈,同步代码执行。在执行的过程中,会判断是同步任务还是异步任务,通过对一些接口的调用,可以产生新的 macro-task 与 micro-task,它们会分别被推入各自的任务队列里。同步代码执行完了,script 脚本会被移出 macro 队列,这个过程本质上是队列的 macro-task 的执行和出队的过程。需要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。因此,我们处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。
也就是说循环是这样一个过程:
先执行宏任务,然后查看是否有微任务队列。如果有,先执行微任务队列中的所有任务,如果没有,会读取宏任务队列中排在最前的任务,执行宏任务的过程中,遇到微任务,依次加入微任务队列。栈空后,再次读取微任务队列里的任务。
4:总结
一句话:
对于浏览器Event loop来说,由于script(整体代码)先执行,所以说MacroTask先于MicroTask执行。
参考文章:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。