宏任务微任务

宏任务

  • 浏览器中:I/O、setTimeout、setInterval、requestAnimationFrame

  • Node中:I/O、setTimeout、setInterval、setImmediate

微任务

  • 浏览器中:MutationObserver、Promise.then/.catch/.finally

  • Node中:process.nextTick 、Promise.then/.catch/.finally

微任务与宏任务执行顺序

JavaScript是单线程的,常用的任务分为同步任务和异步任务。在每轮事件循环中,主线程会先执行完同步任务,再执行异步任务。

  整体JavaScript代码将作为一个宏任务执行,先将同步任务进入主线程执行,异步任务进入事件(Event Table)并注册回调函数(如:success、then、catch等)。当异步事件完成,回调函数进入事件队列等待被调用。而来自不同任务源的任务会进入不同的任务队列。其中setTimeout与setInterval是同源的。

  js引擎Monitoring Process进程会不断的检查主线程执行栈是否为空,一旦为空,就会检查事件队列中是否有等待被调用的函数,如果有,主线程将依次读取回调函数并调用。否则执行下一轮事件循环。

  在每轮事件循环中微任务队列的优先级高于宏任务队列。微任务队列中排队的所有微任务都在同一周期内处理,而这些微任务本身也可以将其他微任务添加到微任务队列中中执行,只有这些微任务全部执行完成时,才会执行下一个宏任务。

(先同步后异步,先微任务,再宏任务)

console.log('script start');  // 同步

setTimeout(function () {
  console.log('setTimeout1');  // 异步
}, 300);

setTimeout(function () {
  console.log('setTimeout2');  // 异步
}, 0);

new Promise(resolve => {
  resolve()
  console.log('promise1');  // 同步
}).then(() => {
  console.log('promise2');  // 异步
})

console.log('script end');  // 同步

// script start
// promise1
// script end
// promise2
// setTimeout2
// setTimeout1

 process.nextTick()先于Promise.then()执行, setTimeout()与setImmediate()执行顺序取决于setTimeout的执行周期与设备性能。

console.log('golbol');

setTimeout(function () {
  console.log('timeout1');
  process.nextTick(function () {
    console.log('timeout1_process');
  })

  new Promise(function (resolve) {
    console.log('timeout1_promise');
    resolve();
  }).then(function () {
    console.log('timeout1_then')
  })
})

setImmediate(function () {
  console.log('immediate1');
  process.nextTick(function () {
    console.log('immediate1_process');
  })

  new Promise(function (resolve) {
    console.log('immediate1_promise');
    resolve();
  }).then(function () {
    console.log('immediate1_then')
  })
})

process.nextTick(function () {
  console.log('process1');
})

new Promise(function (resolve) {
  console.log('promise1');
  resolve();
}).then(function () {
  console.log('promise1_then')
})

setTimeout(function () {
  console.log('timeout2');
  process.nextTick(function () {
    console.log('timeout2_process');
  })

  new Promise(function (resolve) {
    console.log('timeout2_promise');
    resolve();
  }).then(function () {
    console.log('timeout2_then')
  })
})

process.nextTick(function () {
  console.log('process2');
})

new Promise(function (resolve) {
  console.log('promise2');
  resolve();
}).then(function () {
  console.log('promise2_then')
})


setImmediate(function () {
  console.log('immediate2');
  process.nextTick(function () {
    console.log('immediate2_process');
  })

  new Promise(function (resolve) {
    console.log('immediate2_promise');
    resolve();
  }).then(function () {
    console.log('immediate2_then')
  })
})
  • 整体代码作为宏任务执行:

宏任务代码

微任务队列

整体代码

- 输出:global

- 将setTimeout标记为timeout1添加到宏任务队列中

- 将setImmediate标记为immediate1添加到宏任务队列中

- 将process标记为process1添加到微任务队列中

- 输出:promise1。将promise标记为promise1添加到微任务队里

- 将setTimeout标记为timeout2添加到宏任务队列中

- 将process标记为process2添加到微任务队列中

- 输出:promise2。将promise标记为promise2添加到微任务队里

- 将setImmediate2标记为immediate2添加到宏任务队列中

```

global、promise1、promise2

```

宏任务队列

微任务队列

timeout1、timeout2

process1、process2

immediate1、immediate2

promise1、promise2

  主进程事件执行完,执行微任务队列,process.nextTick比promise.then先执行

process1、process2、promise1_then、promise2_then
复制代码
  • 执行setTimeout宏任务队列

宏任务队列

微任务队列

timeout1、timeout2

immediate1、immediate2

  分别执行宏任务队列setTimeout任务源

  1. 输出:timeout1

  1. 将process标记为timeout1_process添加到微任务队列中

  1. 输出:timeout1promise。将promise标记为timeout1then添加到微任务队里

  1. 输出:timeout2

  1. 将process标记为timeout2_process添加到微任务队列中

  1. 输出:timeout2promise。将promise标记为timeout2then添加到微任务队里

timeout1、timeout1_promise、timeout2、timeout2_promise
复制代码

  主进程事件执行完,执行微任务队列

宏任务队列

微任务队列

timeout1process、timeout2process

immediate1、immediate2

timeout1then、timeout2then

  执行微任务队列:

timeout1_process、timeout2_process、timeout1_then、timeout2_then
复制代码
  • 执行setImmediate宏任务队列

宏任务队列

微任务队列

immediate1、immediate2

  分别执行宏任务队列setImmediate任务源

  1. 输出:immediate1

  1. 将process标记为immediate1_process添加到微任务队列中

  1. 输出:immediate1promise。将immediate标记为immediate1then添加到微任务队里

  1. 输出:immediate2

  1. 将process标记为immediate2_process添加到微任务队列中

  1. 输出:immediate2promise。将promise标记为immediate2then添加到微任务队里

immediate1、immediate1_promise、immediate2、immediate2_promise
复制代码

  主进程事件执行完,执行微任务队列

宏任务队列

微任务队列

immediate1process、immediate2process

immediate1then、 immediate2then

  执行微任务队列:

immediate1_process、immediate2_process、immediate1_then、immediate2_then

整体输出

global、promise1、promise2、

process1、process2、promise1_then、promise2_then、

timeout1、timeout1_promise、timeout2、timeout2_promise、

timeout1_process、timeout2_process、timeout1_then、timeout2_then、

immediate1、immediate1_promise、immediate2、immediate2_promise、

immediate1_process、immediate2_process、immediate1_then、immediate2_then

转载 宏任务微任务 - 掘金 (juejin.cn)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值