浅谈JS的微任务和宏任务(附加面试题)

Event Loop

因为JS是单线程,就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。

掌握知识点

  • JS分为同步任务和异步任务
  • 同步任务都在主线程上执行,形成一个执行栈
  • 主线程外,事件触发线程管理者异步任务
  • 一旦执行栈中的所有同步任务执行完毕(此时JS处于空闲),系统就会读取异步任务,将异步任务添加到执行栈中,开始执行

宏任务(macrotask)

这里我们需要记住,浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染
结论:当前宏任务执行完毕,才执行DOM渲染
宏任务包含:

1. 新程序会子程序被直接执行
2. 事件的回调函数
3. setTimeout()和setInterval()
4. I/O
5. UI交互事件
6. setImmediate(Node.js 环境)

微任务(microtask)

记住:在某一个宏任务(macrotask)执行完后,就会将在它执行期间产生的所有微任务(microtask)都执行完毕(在渲染前)。
结论 执行顺序

macrotask -->  microtask --> DOM渲染 

微任务包含

1. Promise.then().catch().finally()
2. Object.observe
3. MutationObserver
4. process.nextTick(Node.js 环境)

运行机制

因为Event Loop 会不断循环队列
所以

1. 执行一个宏任务(栈中没有就从事件队列中获取)
2. 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
3. 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
4. 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
5. 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

async

鄙视题

async function async1() {
      console.log('1')
      await async2()
      console.log('2')
    }
    async function async2() {
      console.log('3')
    }
    console.log('4')
    async1();
    new Promise(function (resolve) {
      console.log('5')
      resolve();
    }).then(function () {
      console.log('6')
    })
    console.log('7')
    // 4 1 3 5 7 2 6

知识点

在查看解题思路前我们要先了解一下知识点

  1. 创建Promise里面的代码会立即执行,但是 then中的函数则是被推送到微任务中去链接: mdn中的描述.

浅谈JS的微任务和宏任务(附加面试题)_第1张图片
2. async 定义的函数也是立即执行
3. async 定义的函数返回值是一个Promise对象

4. 阮一峰老师原话

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

解题思路

6. 程序首次执行(script下的全部代码)算是宏任务,所以调用栈是script
7. 首先执行到console.log('4')  输出4
8. 执行async1()--> 执行console.log('1')--> 执行await async2() --> console.log('3')输出3
因为await执行完毕后会让出线程,跳出当前函数async1,
9. 执行 new Promise() {...} 因为 Promise 是立即执行的 所以执行console.log('5') 输出5
10. 执行resolve() 后 then收到状态 ,将then(function(){console.log('6')}) 推到微任务队列中
11. 执行 console.log('7')  
12. 因为async1中跳出来了,并且后续代码执行完毕,返回到async1中继续执行后续代码 console.log('2')
13. 当前宏任务执行完毕 执行微任务 console.log('6')

参考文档 参考文档1.
但是里卖弄有一个问题,可能是新版浏览器的问题,见下图,在这里插入图片描述
我用的是这个版本的浏览器
浅谈JS的微任务和宏任务(附加面试题)_第2张图片
以下下这两种情况返回的都是 fulfiled
浅谈JS的微任务和宏任务(附加面试题)_第3张图片
所以这个题的结果应该是以下
浅谈JS的微任务和宏任务(附加面试题)_第4张图片
链接: js宏任务与微任务参考.
面试题参考:面试题.

总结

一开始看了面试题参考,但是发现有很多地方看不懂,比如说为什么await会让出线程,然后就去查资料,然后又出现新的疑问,真的是一个面试题炸出这么多问题,谁来救救孩子,好在最后都顺利解决,加油,前端路漫漫~~

你可能感兴趣的:(js,javascript,前端)