day040: 如何理解EventLoop——宏任务和微任务篇

本文深入探讨了JavaScript中的宏任务与微任务概念,解释了它们如何在V8引擎中被处理,以及宏任务队列和延迟队列的工作原理。同时,介绍了微任务的引入目的及执行时机,包括Promise、MutationObserver等常见微任务类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

宏任务(MacroTask)引入

在 JS 中,大部分的任务都是在主线程上执行,常见的任务有:

  1. 渲染事件

  2. 用户交互事件

  3. js脚本执行

  4. 网络请求、文件读写完成事件等等。

为了让这些事件有条不紊地进行,JS引擎需要对之执行的顺序做一定的安排,V8 其实采用的是一种队列的方式来存储这些任务, 即先进来的先执行。模拟如下:

bool keep_running = true;
void MainTherad(){
  for(;;){
    //执行队列中的任务
    Task task = task_queue.takeTask();
    ProcessTask(task);
    
    //执行延迟队列中的任务
    ProcessDelayTask()


    if(!keep_running) //如果设置了退出标志,那么直接退出线程循环
        break; 
  }
}

这里用到了一个 for 循环,将队列中的任务一一取出,然后执行,这个很好理解。但是其中包含了两种任务队列,除了上述提到的任务队列, 还有一个延迟队列,它专门处理诸如setTimeout/setInterval这样的定时器回调任务。

上述提到的,普通任务队列和延迟队列中的任务,都属于宏任务

微任务(MicroTask)引入

对于每个宏任务而言,其内部都有一个微任务队列。那为什么要引入微任务?微任务在什么时候执行呢?

其实引入微任务的初衷是为了解决异步回调的问题。想一想,对于异步回调的处理,有多少种方式?总结起来有两点:

  1. 将异步回调进行宏任务队列的入队操作。

  2. 将异步回调放到当前宏任务的末尾。

如果采用第一种方式,那么执行回调的时机应该是在前面所有的宏任务完成之后,倘若现在的任务队列非常长,那么回调迟迟得不到执行,造成应用卡顿

为了规避这样的问题,V8 引入了第二种方式,这就是微任务的解决方式。在每一个宏任务中定义一个微任务队列,当该宏任务执行完成,会检查其中的微任务队列,如果为空则直接执行下一个宏任务,如果不为空,则依次执行微任务,执行完成才去执行下一个宏任务。

常见的微任务有MutationObserver、Promise.then(或.reject) 以及以 Promise 为基础开发的其他技术(比如fetch API), 还包括 V8 的垃圾回收过程。

Ok, 这便是宏任务微任务的概念,接下来正式介绍JS非常重要的运行机制——EventLoop。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值