EventLoop - 宏任务&微任务 - 普通题目

2020-04-07  本文已影响0人  木头就是我呀

近几天看了好多js基础原理相关的知识。同步代码&异步代码的执行顺序(浏览器的事件循环&宏任务&微任务)一直是面试的高频考题,这里总结一下自己做这种题的思路(流程)。

JS代码中的异步任务可进一步分为宏任务(macrotask)与微任务(microtask)。
宏任务包括:script代码、setTimeout、setInterval、I/O、UI render
微任务包括:promise.then、Object.observe(已废弃)、MutationObserver

 setTimeout(function(){ //s1
   console.log('1')
 });
 new Promise(function(resolve){ // p1-resolve
   console.log('2');
   resolve();
 }).then(function(){ // p1-then
   console.log('3')
 });
 console.log('4');

// 输出 2 4 3 1

步骤:
1. 主代码执行
宏任务队列 = [s1]
进入Promise声明,console.log('2');  ======================> 2
微任务队列 = [p1-then]
console.log('4');  ======================> 4

2. 清掉微任务队列
console.log('3')  ======================> 3
微任务队列 = []

3. 拿出宏任务队列第一项 s1
宏任务队列 = []
console.log('1')  ======================> 1
该宏任务结束
console.log(1);
setTimeout(() => { // s1
   console.log(2);
   Promise.resolve().then(() => { // p1-then
     console.log(3);
   });
 }, 0);
 new Promise((resolve, reject) => { // p2-resolve
   console.log(4);
   resolve(5);
 }).then((data) => { // p2-then
   console.log(data);
 });
 setTimeout(() => { // s2
   console.log(6);
 }, 0);

// 输出 1 4 5 2 3 6

步骤:
1. 主代码执行
console.log(1); ======================> 1
宏任务队列 = [s1]
进入Promise声明   ======================> 4
微任务队列 = [p2-then]
宏任务队列 = [s1,s2]

2. 清掉微任务队列
console.log(data); ======================> 5
微任务队列 = []

3. 拿出宏任务队列中第一项 s1
宏任务队列 = [s2]
console.log(2); ======================> 2
微任务队列 = [p1-then]
该宏任务结束

4. 清空微任务队列
console.log(3); ======================> 3
微任务队列 = []

5. 拿出宏任务队列中第一项 s2
宏任务队列 = []
console.log(6); ======================> 6
该宏任务结束
 async function async1() {
   console.log(1); 
   const result = await async2(); 
   console.log(3);  // p-await
 } 
 async function async2() { 
   console.log(2); 
 } 
 Promise.resolve().then(() => {  // p1
   console.log(4); 
 }); 
 setTimeout(() => {  // s1
   console.log(5); 
 }); 
 async1(); 
 console.log(6);

// 输出 1 2 6 4 3 5

步骤:
1. 主代码执行
微任务队列 = [p1]
宏任务队列 = [s1]
console.log(1) ======================> 1
console.log(2) ======================> 2
await方法返回的是一个promise对象,因此await方法执行完毕的后续代码都应该归入微任务队列,
所以console.log(3)应该作为微任务,追加到微任务队列中。
微任务队列 = [p1, p-await]
console.log(6); ======================> 6

2. 清空微任务队列
console.log(4);  ======================> 4
console.log(3);  ======================> 3
微任务队列 = []

3. 拿出宏任务队列第一项 s1
宏任务队列 = []
console.log(5);  ======================> 5
 setTimeout(() => { // s1
   console.log('setTimeout - 1')
   setTimeout(() => { // s1-1
     console.log('setTimeout - 1 - 1')
   })
   new Promise(resolve => { // p1-resolve
     console.log('setTimeout - 1 - resolve')
     resolve() 
   }).then(() => { // p1-then
     console.log('setTimeout - 1 - then')
     new Promise(resolve => resolve()).then(() => { // p1-then-then
         console.log('setTimeout - 1 - then - then')
     })
   })
 })
 setTimeout(() => { // s2
   console.log('setTimeout - 2')
   setTimeout(() => { // s2-1
     console.log('setTimeout - 2 - 1')
   })
   new Promise(resolve => resolve()).then(() => { // p2-then
     console.log('setTimeout - 2 - then')
     new Promise(resolve => resolve()).then(() => { // p2-then-then
         console.log('setTimeout - 2 - then - then')
     })
   })
 })

// 输出
// setTimeout - 1
// setTimeout - 1 - resolve
// setTimeout - 1 - then
// setTimeout - 1 - then - then 
// setTimeout - 2
// setTimeout - 2 - then
// setTimeout - 2 - then - then
// setTimeout - 1 - 1
// setTimeout - 2 - 1

步骤: 
1. 主代码执行
宏任务队列 = [s1 , s2]

2. 拿出第一个宏任务 s1
宏任务队列 = [s2]
console.log('setTimeout - 1') ======================> setTimeout - 1
宏任务队列 = [s2 , s1-1]
console.log('setTimeout - 1 - resolve') ======================> setTimeout - 1 - resolve
微任务队列 = [p1-then]
s1宏任务结束

3. 清空微任务队列
微任务队列 = []
console.log('setTimeout - 1 - then') ======================> setTimeout - 1 - then
微任务队列 = [p1-then-then]

4. 清空微任务队列
微任务队列 = []
console.log('setTimeout - 1 - then - then') ======================> setTimeout - 1 - then - then

5. 拿出第一个宏任务 s2
宏任务队列 = [s1-1]
console.log('setTimeout - 2') ======================> setTimeout - 2
宏任务队列 = [s1-1 , s2-1]
微任务队列 = [p2-then]

6. 清空微任务队列
微任务队列 = []
console.log('setTimeout - 2 - then') ======================> setTimeout - 2 - then
微任务队列 = [p2-then-then]

7. 清空微任务队列
微任务队列 = []
console.log('setTimeout - 2 - then - then') ======================> setTimeout - 2 - then - then

8. 拿出宏任务队列第一项 s1-1
宏任务队列 = [s2-1]
console.log('setTimeout - 1 - 1') ======================> setTimeout - 1 - 1

9. 拿出宏任务队列第一项 s2-1
宏任务队列 = []
console.log('setTimeout - 2 - 1') ======================> setTimeout - 2 - 1

题目参考自:
https://juejin.im/post/5e01e0f76fb9a01622779fad

上一篇 下一篇

猜你喜欢

热点阅读