前段时间我对于浏览器Event loop中的MacroTask和MicroTask哪一个先执行有所困惑,苦于搜索也没有发现很明确的答案,因而决定深刻探索浏览器Event loop,现有所愚见,想与你们分享,但愿能帮助到那些还在爬坑的人。
1.什么是Event loop?segmentfault
developer.mozilla.org给出的解释是这样的:promise
一个 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。oop
3.同步事件和异步事件怎么处理?post
一开始执行栈空,micro 队列空,macro 队列里有且只有一个 script 脚本(总体代码)。而后全局上下文(script 标签)被推入执行栈,同步代码执行。在执行的过程当中,会判断是同步任务仍是异步任务,经过对一些接口的调用,能够产生新的 macro-task 与 micro-task,它们会分别被推入各自的任务队列里。同步代码执行完了,script 脚本会被移出 macro 队列,这个过程本质上是队列的 macro-task 的执行和出队的过程。须要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。所以,咱们处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。spa
也就是说循环是这样一个过程:
先执行宏任务,而后查看是否有微任务队列。若是有,先执行微任务队列中的全部任务,若是没有,会读取宏任务队列中排在最前的任务,执行宏任务的过程当中,遇到微任务,依次加入微任务队列。栈空后,再次读取微任务队列里的任务。code
4:总结
一句话:server
对于浏览器Event loop来讲,因为script(总体代码)先执行,因此说MacroTask先于MicroTask执行。
参考文章: