当前位置: 首页 > news >正文

js中的微任务和宏任务的理解

在JavaScript中,微任务(Microtask)和宏任务(Macrotask)是异步任务执行机制的重要组成部分,它们共同构成了JavaScript事件循环(Event Loop)的核心逻辑。理解这两个概念对于编写高性能、无阻塞的代码至关重要。

1. 基本概念

宏任务(Macrotask)
  • 定义:由浏览器或Node.js环境提供的异步任务,通常是一些离散的、独立的操作。
  • 常见宏任务
    • setTimeoutsetInterval
    • setImmediate(Node.js)
    • requestAnimationFrame(浏览器)
    • I/O操作(如文件读取、网络请求)
    • UI渲染(浏览器)
微任务(Microtask)
  • 定义:JavaScript引擎自身提供的异步任务,通常是需要在当前任务完成后立即执行的操作。
  • 常见微任务
    • Promise.then()Promise.catch()Promise.finally()
    • MutationObserver(浏览器)
    • process.nextTick(Node.js)
    • queueMicrotask(ES2020+)

2. 执行顺序规则

JavaScript的事件循环执行机制遵循以下规则:

  1. 执行栈(Call Stack) 为空时,事件循环开始处理任务队列。
  2. 宏任务队列 每次只取一个任务执行,执行完毕后立即处理 微任务队列
  3. 微任务队列 会被清空(依次执行所有微任务),直到队列为空。
  4. 微任务队列清空后:
    • 浏览器可能进行 UI渲染(仅在浏览器环境)。
    • 事件循环回到步骤2,继续处理下一个宏任务。

总结宏任务 → 清空微任务队列 → UI渲染 → 下一个宏任务

3. 经典示例分析

console.log('1. 主线程开始');// 宏任务1
setTimeout(() => {console.log('2. setTimeout 回调执行');// 微任务1Promise.resolve().then(() => {console.log('3. setTimeout 内部 Promise 微任务执行');});
}, 0);// 微任务2
Promise.resolve().then(() => {console.log('4. 主线程 Promise 微任务执行');// 微任务3queueMicrotask(() => {console.log('5. queueMicrotask 微任务执行');});
});console.log('6. 主线程结束');

执行顺序解析

  1. 主线程 执行:

    • 输出 1. 主线程开始
    • setTimeout 被放入 宏任务队列
    • Promise.then 被放入 微任务队列(微任务2)。
    • 输出 6. 主线程结束
  2. 微任务队列 执行:

    • 执行微任务2,输出 4. 主线程 Promise 微任务执行
    • queueMicrotask 被加入微任务队列(微任务3)。
    • 继续执行微任务3,输出 5. queueMicrotask 微任务执行
  3. 宏任务队列 执行:

    • 执行宏任务1(setTimeout 回调),输出 2. setTimeout 回调执行
    • Promise.then 被加入微任务队列(微任务1)。
    • 清空微任务队列,执行微任务1,输出 3. setTimeout 内部 Promise 微任务执行

最终输出顺序

1. 主线程开始
6. 主线程结束
4. 主线程 Promise 微任务执行
5. queueMicrotask 微任务执行
2. setTimeout 回调执行
3. setTimeout 内部 Promise 微任务执行

4. 实际应用场景

4.1 微任务的应用
  • Promise链式调用:确保回调按顺序执行,不阻塞主线程。
    fetchData().then(processData).then(updateUI).catch(handleError);
    
  • DOM变更后立即操作:使用 MutationObserver 监听DOM变化后执行回调。
4.2 宏任务的应用
  • 定时器:实现延迟执行或周期性任务。
    setTimeout(() => {// 延迟执行的代码
    }, 1000);
    
  • 分批处理大量数据:避免长时间阻塞主线程。
    function processLargeData(data) {const batchSize = 1000;let index = 0;function processBatch() {const batch = data.slice(index, index + batchSize);// 处理当前批次数据index += batchSize;if (index < data.length) {setTimeout(processBatch, 0); // 使用宏任务拆分处理}}processBatch();
    }
    

5. 微任务 vs 宏任务的关键区别

特性微任务(Microtask)宏任务(Macrotask)
执行时机当前任务结束后立即执行(在渲染前)下一次事件循环开始时执行(可能在渲染后)
队列清空规则一次性清空所有微任务每次只处理一个宏任务
触发频率高(可能在一次事件循环中多次触发)低(每次事件循环只处理一个)
典型场景Promise回调、DOM变更监听定时器、I/O操作、UI渲染

6. 注意事项

  1. 微任务阻塞渲染:如果微任务队列过长,会导致UI长时间无法渲染,造成页面卡顿。
  2. 合理选择任务类型
    • 需要立即执行的异步操作(如Promise链)使用微任务。
    • 需要离散执行的操作(如定时器、大数据处理)使用宏任务。
  3. 浏览器兼容性queueMicrotask 是较新的API,旧浏览器可能需要使用 Promise.resolve().then() 替代。

通过理解微任务和宏任务的执行机制,你可以更精确地控制代码的执行顺序,避免性能问题,提升用户体验。

http://www.dtcms.com/a/286682.html

相关文章:

  • python 实现将文件的非零数据扇区进行提取,并以偏移地址进行命名保存
  • AI(day10)模块化编程概念(模块、包、导入)及常见系统模块总结和第三方模块管理
  • AE PDW2200电源射频手侧使用安装说明含电路图
  • 70 gdb attach $pid, process 2021 is already traced by process 2019
  • 反序列化漏洞3-反序列化漏洞讲解演示
  • 4. PyQGIS整体框架详解
  • Agent AI(3):Agent分类
  • day30——零基础学嵌入式之线程2.0
  • 多线程-2-线程间通信
  • 推荐算法召回:架构理解
  • 【RK3576】【Android14】开发环境搭建
  • Windows 下 VS2019 编译 libevent-2.1.10 库
  • React 实现人员列表多选、全选与取消全选功能
  • 大疆司空2私有化部署报错解决方案
  • 谷歌浏览器Chrome的多用户配置文件功能
  • Python分组柱形图绘制全攻略
  • 题解:CF1866D Digital Wallet
  • 熔断和降*的区别
  • 使用pt-toolkit工具包进行MySQL性能优化实战指南
  • 算法训练营day24 回溯算法③ 93.复原IP地址 、78.子集、 90.子集II
  • AWS SSL证书无缝迁移完整指南 - 零业务中断方案
  • Python 进程间通信:TCP安全加密数据传输
  • H3CNE小小综合实验
  • 模拟数据生成---使用NGS数据模拟软件VarBen
  • SLM343CK-DG Sillumin数明半导体高性能LED驱动芯片 抗干扰+耐高温 车载照明专用
  • 二叉树(建立 + 遍历 + 拓展)
  • 外部DLL创建及使用
  • 灵巧手(具身智能入门十一)
  • if (a == 1 a == 2 a == 3)返回true的问题思考
  • NVIDIA 驱动安装失败问题排查与解决(含离线 GCC 工具链安装全过程)