宏任务(macrotask )和微任务(microtask )

1 篇文章 0 订阅
1 篇文章 0 订阅
本文解析了宏任务和微任务在JavaScript异步执行中的角色,通过实例阐述了它们的执行顺序及在setTimeout、Promise和UI交互中的应用。重点介绍了script标签下的宏任务和Promise.then等微任务的区别与配合。
摘要由CSDN通过智能技术生成

宏任务(macrotask )和微任务(microtask )表示异步任务的两种分类。

在挂起任务时,主进程的任务执行完成,JS 引擎会将所有异步事件任务按照类别分到这两个队列中,首先在 宏任务(macrotask ) 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 当前宏任务下的所有微任务(microtask ) 顺序执行;之后再取 宏任务(macrotask ),周而复始,直至两个队列的任务都取完

## 宏任务包含 ##

**script标签下的上下文就是一个大的宏任务**

 

  

    script(整体代码)

    setTimeout

    setInterval

    I/O

    UI交互事件

    postMessage

    MessageChannel

    setImmediate(Node.js 环境)

  

## 微任务包含 ##

 

  

    Promise.then

    Object.observe

    MutaionObserver

    process.nextTick(Node.js 环境)

  

如图所示:

## 主进程与异步事件的执行机制 ##

![active](/images/js/9.png)

## 宏任务和微任务之间的关系 ##

![active](/images/js/10.png)


 

举个例子



setTimeout(() => {

    //执行后 回调一个宏事件

    console.log('内层宏事件3')

}, 0)

console.log('外层宏事件1');

new Promise((resolve) => {

    console.log('外层宏事件2');

    resolve()

}).then(() => {

    console.log('微事件1');

}).then(()=>{

    console.log('微事件2')

})

• 首先浏览器执行js进入第一个宏任务(script上下文)进入主线程, 遇到 setTimeout(第二个宏任务)  分发到宏任务Event Queue中

• 遇到 console.log() 直接执行 输出 外层宏事件1

• 遇到 Promise, new Promise 直接执行 输出 外层宏事件2

• 执行then 被分发到微任务Event Queue中

•第一轮宏任务执行结束,开始执行微任务 打印 '微事件1' '微事件2'

•第一轮微任务执行完毕,执行第二轮宏事件,打印setTimeout里面内容'内层宏事件3'


 

**再来看一个例子**

 

  

//主线程直接执行

console.log('1');

//丢到宏事件队列中

setTimeout(function() {

    console.log('2');

    process.nextTick(function() {

        console.log('3');

    })

    new Promise(function(resolve) {

        console.log('4');

        resolve();

    }).then(function() {

        console.log('5')

    })

})

//微事件1

process.nextTick(function() {

    console.log('6');

})

//主线程直接执行

new Promise(function(resolve) {

    console.log('7');

    resolve();

}).then(function() {

    //微事件2

    console.log('8')

})

//丢到宏事件队列中

setTimeout(function() {

    console.log('9');

    process.nextTick(function() {

        console.log('10');

    })

    new Promise(function(resolve) {

        console.log('11');

        resolve();

    }).then(function() {

        console.log('12')

    })

})

  

• 首先浏览器执行js进入第一个宏任务进入主线程, 直接打印console.log('1')

• 遇到 setTimeout  分发到宏任务Event Queue中

• 遇到 process.nextTick 丢到微任务Event Queue中

• 遇到 Promise, new Promise 直接执行 输出 console.log('7');

• 执行then 被分发到微任务Event Queue中

•第一轮宏任务执行结束,开始执行微任务 打印 6,8

•第一轮微任务执行完毕,执行第二轮宏事件,执行setTimeout

•先执行主线程宏任务,在执行微任务,打印'2,4,3,5'

•在执行第二个setTimeout,同理打印 ‘9,11,10,12’

•整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。

以上是在浏览器环境下执行的数据,只作为宏任务和微任务的分析,我在node环境下测试打印出来的顺序为:1,7,6,8,2,4,9,11,3,10,5,12。node环境执行结果和浏览器执行结果不一致的原因是:浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现。libuv库流程大体分为6个阶段:timers,I/O callbacks,idle、prepare,poll,check,close callbacks,和浏览器的microtask,macrotask那一套有区别。

个人小程序:

采用uni-app+云服务开发,有喜欢的可以@我,免费开放代码和手把手教你搭建

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fzl_1996

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值