事件循环机制,同步异步、宏任务微任务等是怎么执行的
看了很多对于微任务宏任务事件循环的讲解,有很多不同的地方,有人说代码块是宏任务,所以事件循环是宏->微的循环,还有人说先微后宏任务。
常见宏任务包括:
- 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