事件循环机制,同步异步、宏任务微任务等是怎么执行的

看了很多对于微任务宏任务事件循环的讲解,有很多不同的地方,有人说代码块是宏任务,所以事件循环是宏->微的循环,还有人说先微后宏任务。

常见宏任务包括:

  • setTimeout
  • setInterval
  • setImmendiate
  • I/O

常见微任务包括

  • promise.then等
  • catch、finally
  • MutationObserver
  • process.nextTick(node)

执行的过程大概是:

  • 整体script代码进入执行栈执行,依次执行所有同步代码,将遇到的异步代码分为宏、微任务,各自产生的回调分别放入各自的队列(宏任务队列微任务队列是不同的队列)。
  • 此时等待主线执行栈执行同步代码结束后,开始一次执行微任务队列中代码直到微任务队列为空,再执行宏任务队列中下一个宏任务,依次循环。
  • 宏任务、微任务中又可能包括宏、微任务,仍然按照以上规则处理,顺序不能乱。

 

注意:promise中.then内才是异步微任务,new promise中前面部分是同步任务,setTimeout也只有里面回调才会进入异步队列。

 

 

 1             setTimeout(() => {
 2               console.log(1);
 3               setTimeout(() => {
 4                 console.log(3)
 5               }, 0)
 6               new Promise(resolve => {
 7                 resolve()
 8                 console.log('promise')
 9               }).then(() => {
10                 console.log('then')
11               })
12             }, 0)
13             
14             setTimeout(() => {
15               console.log(2)
16             }, 0)
17             console.log('first')

以上代码的执行过程:同步代码console.log(first)进入主线程执行输出,将俩个宏任务回调依次进入宏任务队列取名macro1 macro2。随后发现微任务队列为空,则宏任务队列中macro1进入执行栈,执行同步代码console.log(1)、console.log('promise');发现并将宏任务macro3放入宏任务队列中,.then中内容为微任务micro1放入微任务队列中。此时一轮结束,宏任务队列中是 macro2、macro3,微任务队列中是micro1。接下来重新循环,执行微任务micro1,结束后执行macro2、macro3。最后结果显示 first、1、promise、then、2、3.

总结一下面试题看代码输出的套路:

  • 从上往下,同步直接执行,异步分发宏任务或者微任务
  • 碰到MacroTask直接执行,并且把回调函数放入任务执行队列中(下次事件循环执行)同理碰到微任务直接执行;把回调函数放入微任务执行队列中(本次事件循环执行)
  • 当同步任务执行完毕后,去执行微任务microtask。(微任务队列清空)
  • 由此进入下一轮事件循环:执行宏任务 任务 (setTimeout,setInterval,callback)


学习自:
https://zhuanlan.zhihu.com/p/139967525

https://juejin.cn/user/2999123452373735

posted on 2021-09-18 23:50  小二上酒~  阅读(93)  评论(0编辑  收藏  举报