微任务和宏任务有什么区别

简介: 微任务和宏任务是JavaScript异步编程中的两个概念。宏任务包括整体代码块、setTimeout等,微任务有Promise、MutationObserver等。主要区别在于执行时机:每次事件循环中,宏任务只执行一个,而微任务会在当前宏任务结束后、下一个宏任务开始前全部执行完毕。
  1. 定义与概念

    • 宏任务(Macro - Task):宏任务是浏览器或JavaScript运行环境中的一个较大的任务单元,通常包括一些比较耗时或者不那么紧急的操作。例如,script(整体脚本)、setTimeoutsetIntervalI/O操作(如Ajax请求)、postMessageMessageChannel等都属于宏任务。它们构成了任务队列(Task Queue)中的主要部分,这些任务的执行顺序遵循一定的规则,在事件循环(Event Loop)中按顺序逐个被处理。
    • 微任务(Micro - Task):微任务是一种相对较小、更紧急的任务,它们通常是在当前宏任务执行结束后,下一个宏任务开始之前需要立即执行的任务。常见的微任务包括Promise.then()MutationObserverprocess.nextTick(在Node.js环境下)等。微任务队列(Micro - Task Queue)用于存储这些微任务,并且在宏任务执行间隙优先清空微任务队列。
  2. 执行顺序与时机

    • 宏任务执行顺序:在JavaScript的单线程执行模型中,首先执行全局script代码,这是第一个宏任务。当这个宏任务执行过程中遇到异步的宏任务(如setTimeout),会将其回调函数添加到宏任务队列的末尾。只有当当前宏任务以及微任务队列都为空时,才会从宏任务队列中取出下一个宏任务执行。例如:
      console.log('Script start');
      setTimeout(() => {
             
      console.log('Timeout 1');
      }, 0);
      setTimeout(() => {
             
      console.log('Timeout 2');
      }, 0);
      console.log('Script end');
      
    • 在这个例子中,首先执行script这个宏任务,打印Script start,然后遇到两个setTimeout,它们的回调函数被添加到宏任务队列。接着打印Script end,此时当前宏任务结束。由于微任务队列没有任务,所以开始从宏任务队列中取出任务执行,先执行第一个setTimeout的回调函数打印Timeout 1,再执行第二个setTimeout的回调函数打印Timeout 2
    • 微任务执行顺序:在每个宏任务执行结束后,JavaScript引擎会立即检查微任务队列。如果微任务队列中有任务,会按照先进先出(FIFO)的顺序依次执行这些微任务,直到微任务队列清空。例如:
      console.log('Script start');
      const promise1 = Promise.resolve();
      promise1.then(() => {
             
      console.log('Promise 1');
      });
      const promise2 = Promise.resolve();
      promise2.then(() => {
             
      console.log('Promise 2');
      });
      console.log('Script end');
      
    • 在这里,首先执行script宏任务,打印Script start。然后promise1promise2.then回调函数作为微任务被添加到微任务队列。接着打印Script end,此时当前宏任务结束,开始执行微任务队列中的任务,按照添加顺序先打印Promise 1,再打印Promise 2
  3. 对应用性能和行为的影响

    • 宏任务对性能的影响:由于宏任务相对比较耗时,过多的宏任务或者长时间运行的宏任务可能会导致页面的延迟和卡顿。例如,一个复杂的setInterval定时器在每次执行回调函数时进行大量的计算或者DOM操作,可能会占用较长的时间,使得后续的任务(包括渲染任务)被延迟。特别是当宏任务中包含I/O操作(如网络请求)时,等待响应的时间可能会不确定,这也会影响整个应用的响应性能。
    • 微任务对性能的影响:微任务通常用于处理一些对及时性要求较高的操作,它们的执行相对比较快速。但是,如果微任务队列中的任务过多或者某个微任务执行时间过长,也可能会阻塞下一个宏任务的执行,从而影响到整个事件循环的节奏。不过,由于微任务本身是在宏任务间隙执行的,所以在合理使用的情况下,它们可以帮助我们在不阻塞主要任务流程的情况下及时处理一些小的、重要的操作,如更新UI状态等。
    • 应用行为方面的差异:在应用行为上,宏任务更适合用于处理一些可以延迟执行或者周期性执行的任务,如定时更新数据、延迟加载资源等。而微任务则常用于在异步操作完成后立即进行一些后续处理,并且这些处理通常与当前的执行上下文紧密相关,如在Promise成功或失败后立即进行相应的状态更新或者错误处理。例如,在一个基于Promise的异步数据加载应用中,使用微任务来更新UI显示加载成功的数据,能够确保在数据加载完成后及时、同步地更新界面,提供更好的用户体验。
相关文章
|
JavaScript 前端开发 Java
vue3-element-admin 项目说明文档
vue3-element-admin 项目说明文档
|
网络协议 算法 数据库
计算机网络实验(华为eNSP模拟器)——第十四章 RIP协议和OSPF协议
计算机网络实验(华为eNSP模拟器)——第十四章 RIP协议和OSPF协议
计算机网络实验(华为eNSP模拟器)——第十四章 RIP协议和OSPF协议
|
4月前
|
存储 缓存 编译器
依赖管理(go mod)
上部分,我们介绍了使用GOPATH的痛点:多个项目无法共享同一个GOPATH,虽然vendor仍然无法多个项目无法共享同一个GOPATH,但是它提供了一种机制,让项目的依赖隔离而不互相干扰。版本格式 v(major).(minorr).(patch)中的 major 指的是大版本,minor 指的是小版本,patch 指的是补丁版本。从GOPATH到vendor,再到Go Module,这是一个不断演进的过程,了解每代依赖管理的痛点,能够更好的明白下一代依赖管理的初衷。
221 1
|
JavaScript
Node.js npm设置淘宝npm镜像
Node.js npm设置淘宝npm镜像
2740 0
|
人工智能 搜索推荐 Docker
手把手教你使用 Ollama 和 LobeChat 快速本地部署 DeepSeek R1 模型,创建个性化 AI 助手
DeepSeek R1 + LobeChat + Ollama:快速本地部署模型,创建个性化 AI 助手
8437 119
手把手教你使用 Ollama 和 LobeChat 快速本地部署 DeepSeek R1 模型,创建个性化 AI 助手
|
缓存 前端开发 JavaScript
理解 React 的 Fiber 架构
【8月更文挑战第6天】 理解 React 的 Fiber 架构
1289 1
|
JavaScript API
uniapp实现录音功能和播放功能
uniapp实现录音功能和播放功能
|
存储 监控 NoSQL
Redis集群方案汇总:概念性介绍
本文介绍了Redis的三种高可用和分布式解决方案:**Redis Replication(主从复制)**、**Redis Sentinel(哨兵模式)** 和 **Redis Cluster(集群模式)**。Redis Replication实现数据备份和读写分离,适合数据安全和负载均衡场景;Redis Sentinel提供自动故障转移和监控功能,适用于读写分离架构;Redis Cluster通过分布式存储和自动故障转移,解决单点性能瓶颈,适合大规模数据和高并发场景。文中还详细描述了各方案的工作原理、优缺点及适用场景。
509 0
|
前端开发
HTML+CSS 速成10分钟!一键实现你的后台管理系统首页梦想!
HTML+CSS 速成10分钟!一键实现你的后台管理系统首页梦想!
|
安全 Android开发 数据安全/隐私保护
Android vs. iOS:移动操作系统的巅峰对决###
【10月更文挑战第18天】 本文深入探讨了Android与iOS两大移动操作系统的核心差异、优势与不足,从用户体验、应用生态、系统更新与安全性等多个维度进行了全面对比。我们旨在揭示两大平台背后的设计理念,帮助用户根据自身需求做出更明智的选择。Android以其开放性和高度可定制性著称,为开发者和用户提供了广阔的创新空间;而iOS则凭借其封闭的生态系统和严格的质量控制,提供了流畅且一致的用户体验。两大系统各有千秋,竞争与共生中推动着移动通信技术的不断进步。 ###

热门文章

最新文章