微任务类型有哪些?含Promise和MutationObserver
本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《微任务包括:Promise.then/catch/finally、queueMicrotask、MutationObserver、Object.observe(已废弃)等。》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~
微任务主要由Promise回调、MutationObserver和queueMicrotask产生。1.Promise的.then()、.catch()、.finally()会在状态变化后将回调放入微任务队列;2.MutationObserver用于监听DOM变化,其回调作为微任务批量处理以优化性能;3.queueMicrotask是ES2021新增API,允许开发者显式安排微任务。这些微任务会在当前宏任务执行完毕后立即全部执行,确保异步操作顺序可控并优化UI更新,从而提升代码执行的一致性和性能表现。
JavaScript事件循环中,会产生微任务的操作主要集中在几个特定场景:Promise的回调函数(包括.then()
, .catch()
, .finally()
),DOM的MutationObserver
回调,以及通过queueMicrotask()
API显式安排的任务。这些微任务会在当前宏任务(比如一次脚本执行、一个定时器回调)执行完毕后,但在下一个宏任务开始之前,被一并处理掉。

要深入理解微任务,我们得先把它放到JavaScript事件循环的大背景里看。我个人觉得,理解这个机制,是掌握JS异步编程的关键一步,否则很多时候你会发现代码执行顺序和你想的不一样,尤其是在处理UI更新或者复杂的异步流时。
简单来说,事件循环就像个永动机,它不停地检查两类任务队列:宏任务队列(Macrotask Queue)和微任务队列(Microtask Queue)。当我们执行一段JS代码时,它本身就是一个宏任务。这段宏任务执行过程中,如果遇到Promise的.then()
回调,或者DOM发生了变化触发了MutationObserver
,这些回调并不会立刻执行。它们会被悄悄地扔进一个叫“微任务队列”的地方。

一个宏任务执行完了,事件循环并不会马上跳到下一个宏任务。它会先去看看微任务队列里有没有东西。如果有,它就会把队列里所有的微任务,一个接一个地、不间断地执行完,直到队列清空。这个过程是“原子性”的,意思是微任务队列一旦开始清空,就不会被打断,直到所有微任务都执行完毕,才会进行浏览器渲染(如果是在浏览器环境)或者去取下一个宏任务。
所以,核心逻辑就是:一个宏任务 -> 清空所有微任务 -> 渲染(浏览器特有) -> 下一个宏任务。理解这个顺序,你就能明白为什么Promise.resolve().then(...)
会比setTimeout(..., 0)
先执行了。

Promise回调为什么是微任务,它和异步有什么关系?
Promise回调被设计成微任务,这背后其实有很深层的考量。你想啊,Promise是为了解决回调地狱,让异步代码更易读、更可控。如果它的回调(比如then
里头的函数)是宏任务,那会发生什么?
举个例子,假设你有一个Promise链,每一个then
都对应一个宏任务。那么,当你执行完第一个then
后,事件循环可能就会去处理其他的宏任务,比如一个setTimeout
,或者甚至进行一次页面渲染,然后才回来执行你的下一个then
。这会导致什么问题?
- 执行顺序不确定性增加: 你的Promise链会被其他宏任务“打断”,导致链式调用的逻辑变得难以预测。
- UI更新的抖动: 如果Promise的某个步骤需要更新UI,而它又是宏任务,那么UI可能会在Promise链的中间步骤被多次更新,造成不必要的重绘和性能损耗,甚至出现闪烁。
把Promise回调设计成微任务,就完美地解决了这些问题。当一个Promise状态从pending变为fulfilled或rejected时,其对应的then
/catch
/finally
回调会被立即放入微任务队列。这意味着:
- 紧密耦合: 这些回调会紧跟着当前正在执行的同步代码和所有其他微任务之后执行,确保了Promise链的连续性和“立即性”,它们不会被其他宏任务插队。
- UI更新优化: 在一个宏任务内部,所有由它触发的微任务都会在渲染之前执行。这样,即使你的Promise链条很长,所有相关的DOM操作和数据更新都可以在同一次渲染前完成,避免了多次不必要的重绘,提供了更流畅的用户体验。
我个人觉得,这是Promise设计上最精妙的地方之一,它在保证异步性的同时,又通过微任务机制提供了接近同步的执行确定性。
除了Promise,还有哪些常见的操作会产生微任务,它们有什么用?
除了Promise,微任务的家族成员还有几个。最常见的,我觉得是MutationObserver
和相对较新的queueMicrotask
。
1. MutationObserver
这玩意儿听名字就知道跟“变动观察”有关,它就是用来监听DOM树变化的。比如说,你想知道页面上某个元素的属性变了没有,或者子节点被添加删除了没有,MutationObserver
就能派上用场。
它的回调函数,也就是当DOM变化被观察到时执行的那个函数,就是作为微任务被安排的。为什么是微任务?因为DOM变化可能非常频繁,而且很多时候,一个小的DOM操作可能会连锁引发一系列变化。如果MutationObserver
的回调是宏任务,那每次DOM变动都可能触发一次宏任务,造成大量的上下文切换和不必要的UI重绘。
作为微任务,MutationObserver
的回调就能在当前宏任务结束时,批量处理所有观察到的DOM变化。这意味着,即使你在一个宏任务里对DOM进行了十几次修改,MutationObserver
的回调也只会执行一次(或者说,它会收集所有变化,然后一次性通知你),而且是在浏览器渲染之前。这大大提升了性能,避免了UI的抖动和不必要的计算。
2. queueMicrotask()
这个API是ES2021引入的,它的目的非常明确:允许开发者直接、显式地将一个函数安排为微任务。
console.log('同步代码开始'); queueMicrotask(() => { console.log('这是一个微任务'); }); Promise.resolve().then(() => { console.log('这是另一个微任务 (Promise)'); }); console.log('同步代码结束'); // 实际输出顺序: // 同步代码开始 // 同步代码结束 // 这是一个微任务 // 这是一个另一个微任务 (Promise)
你可能会问,有了Promise,有了setTimeout(0)
,为什么还需要queueMicrotask
?它的价值在于,它提供了一个比setTimeout(0)
更“即时”的异步执行机制。setTimeout(0)
实际上是把任务放到了宏任务队列的末尾,它会等待当前所有微任务和可能的渲染完成后才执行。而queueMicrotask
则保证了你的回调会在当前宏任务结束后,所有其他微任务执行之前或之中(取决于入队顺序)执行。
我个人觉得,queueMicrotask
在某些高级场景下非常有用,比如当你需要确保某个操作在UI更新前完成,但又不想引入Promise的额外开销时。它给了开发者更细粒度的控制权,让你能更精确地控制异步代码的执行时机。
微任务与宏任务的执行顺序和区别,对实际开发有什么影响?
理解微任务和宏任务的根本区别以及它们的执行顺序,我觉得是深入前端优化的一个必经之路。说白了,它们决定了你的异步代码什么时候真正跑起来。
核心区别:
- 宏任务 (Macrotasks): 可以理解为一次“完整”的事件循环周期。
到这里,我们也就讲完了《微任务类型有哪些?含Promise和MutationObserver》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

- 上一篇
- ES6trimStart去除空格详解

- 下一篇
- Golang优化云原生启动,轻量二进制冷启动优势解析
-
- 文章 · 前端 | 1分钟前 |
- JS解构赋值使用教程
- 149浏览 收藏
-
- 文章 · 前端 | 3分钟前 |
- Promise.allSettled使用方法详解
- 347浏览 收藏
-
- 文章 · 前端 | 3分钟前 |
- 宏任务与微任务区别详解
- 413浏览 收藏
-
- 文章 · 前端 | 12分钟前 |
- 事件循环与缓存策略如何关联
- 177浏览 收藏
-
- 文章 · 前端 | 13分钟前 |
- JS对象转JSON字符串方法详解
- 325浏览 收藏
-
- 文章 · 前端 | 16分钟前 | JavaScript 性能优化 倒计时 setInterval 时间差
- JS倒计时实现方法及代码示例
- 200浏览 收藏
-
- 文章 · 前端 | 21分钟前 |
- CSS移动端触摸反馈优化技巧
- 207浏览 收藏
-
- 文章 · 前端 | 24分钟前 | JavaScript 原型链 hasOwnProperty Object.hasOwn 属性判断
- 如何判断对象自身属性?
- 277浏览 收藏
-
- 文章 · 前端 | 24分钟前 |
- HTML中如何设置aria-live区域?
- 103浏览 收藏
-
- 文章 · 前端 | 26分钟前 | 动态更新 DOM操作 事件冒泡 事件委托 JavaScript数组
- JavaScript事件委托实现技巧
- 135浏览 收藏
-
- 文章 · 前端 | 27分钟前 |
- 事件循环与WebSockets如何配合工作
- 277浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 96次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 89次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 107次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 98次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 98次使用
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览
-
- UI设计中为何选择绝对定位的智慧之道
- 2024-02-03 501浏览