浅谈宏任务跟微任务的理解

在JavaScript的事件循环(Event Loop)中,任务被分为宏任务(MacroTask)和微任务(MicroTask)两种。这两种任务类型在事件循环中有不同的处理优先级和执行时机。

宏任务(MacroTask)

宏任务包括:script(整个代码脚本)、setTimeout、setInterval、setImmediate(Node.js环境)、I/O、UI渲染等。每个宏任务都会触发一个新的事件循环。

宏任务的特点是:每个宏任务都会开始一个新的任务队列,并且只有当前宏任务队列中的所有任务都执行完成后,才会检查微任务队列并执行其中的任务。

微任务(MicroTask)

微任务包括:Promise的then和catch、MutationObserver(浏览器环境)、process.nextTick(Node.js环境)等。微任务会在每个宏任务之后立即执行,即在一个宏任务执行完后,会立即执行所有微任务,然后再开始下一个宏任务。

微任务的特点是:在当前宏任务执行完后,会立即执行所有微任务,无需等待下一个宏任务。

结合例子谈谈

下面是一个结合了宏任务和微任务的例子:

console.log('1. 开始'); // 宏任务

setTimeout(function() {
  console.log('2. setTimeout回调'); // 宏任务
  Promise.resolve().then(function() {
    console.log('4. Promise在setTimeout中回调'); // 微任务
  });
}, 0);

process.nextTick(function() {
  console.log('3. process.nextTick回调'); // 微任务
});

new Promise(function(resolve) {
  console.log('5. Promise创建'); // 微任务
  resolve();
}).then(function() {
  console.log('6. Promise在全局作用域中回调'); // 微任务
});

setTimeout(function() {
  console.log('7. 第二个setTimeout回调'); // 宏任务
  process.nextTick(function() {
    console.log('8. process.nextTick在第二个setTimeout中回调'); // 微任务
  });
}, 0);

console.log('9. 结束'); // 宏任务

在这个例子中,我们有多个宏任务和微任务交织在一起。现在,我们来分析它们的执行顺序:

  1. 执行console.log('1. 开始'),这是第一个宏任务。
  2. 接着,我们遇到setTimeout,它会在当前宏任务结束后被放入宏任务队列。
  3. 然后,我们有一个process.nextTick,它是一个微任务,会在当前宏任务结束后、下一个宏任务开始前立即执行。因此,它会打印3. process.nextTick回调
  4. 接下来,我们创建了一个新的Promise,并在其创建时执行了console.log('5. Promise创建'),这是微任务。
  5. Promise被解析时,它的then方法中的回调函数会被放入微任务队列。但是,由于前面已经有了一个process.nextTick微任务,因此这个Promise的回调会等待process.nextTick执行完毕后再执行。
  6. 在执行完所有的微任务后(即process.nextTickPromise的回调),我们回到宏任务队列,并执行setTimeout的回调。此时,会打印2. setTimeout回调
  7. setTimeout的回调中,我们又创建了一个新的Promise,并在其解析后执行了console.log('4. Promise在setTimeout中回调')。这是一个微任务,但由于它是在setTimeout的回调中创建的,因此会等待setTimeout的宏任务执行完毕后再执行。
  8. setTimeout的宏任务和其中的微任务都执行完毕后,我们再次回到宏任务队列,并执行第二个setTimeout的回调。此时,会打印7. 第二个setTimeout回调
  9. 在第二个setTimeout的回调中,我们又有一个process.nextTick微任务,它会在当前宏任务结束后、下一个宏任务开始前立即执行。因此,它会打印8. process.nextTick在第二个setTimeout中回调
  10. 最后,执行console.log('9. 结束'),这是最后一个宏任务。

因此,上述代码的输出结果将是:

1. 开始
9. 结束
3. process.nextTick回调
5. Promise创建
6. Promise在全局作用域中回调
2. setTimeout回调
4. Promise在setTimeout中回调
7. 第二个setTimeout回调
8. process.nextTick在第二个setTimeout中回调

这个例子清楚地展示了宏任务和微任务在JavaScript事件循环中的执行顺序。宏任务之间互不影响,每个宏任务都会开始一个新的任务队列,并在其结束后检查并执行微任务队列中的所有任务。微任务则会在当前宏任务结束后、下一个宏任务开始前立即执行。这种机制允许我们更精细地控制代码的执行顺序,尤其是在需要处理异步操作时。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值