news 2026/2/22 21:13:54

JavaScript事件循环:餐厅里的“宏任务”与“微任务”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaScript事件循环:餐厅里的“宏任务”与“微任务”

欢迎使用我的小程序👇👇👇👇 俱好用助手功能介绍


大家好!今天我们来聊聊JavaScript中那个让人又爱又恨的话题——事件循环中的宏任务微任务。别担心,我不会用那些晦涩难懂的专业术语轰炸你,而是用一个超有意思的比喻带你理解这个概念!

一个让人困惑的例子

先看这段代码,猜猜它会按什么顺序输出?

console.log('1. 开始点餐');setTimeout(()=>{console.log('6. 20分钟后,主菜来了');},0);Promise.resolve().then(()=>{console.log('4. 先上开胃小菜');});console.log('2. 点完餐了');Promise.resolve().then(()=>{console.log('5. 再上汤品');});console.log('3. 等待上菜');// 实际输出顺序:// 1. 开始点餐// 2. 点完餐了// 3. 等待上菜// 4. 先上开胃小菜// 5. 再上汤品// 6. 20分钟后,主菜来了

咦?setTimeout不是设置0毫秒吗,为什么最后才执行?这就是宏任务和微任务在搞鬼!

餐厅比喻:理解事件循环

想象一下JavaScript引擎就像一家餐厅:

主厨(JavaScript引擎)只能一次做一件事,但他有个聪明的系统来处理所有订单。

点餐台(调用栈)是主厨当前正在做的菜,一次只能做一道。

等待区(任务队列)是所有等待被做的菜,分为两个区域:

  • VIP区(微任务队列):开胃小菜、汤品等优先处理的
  • 普通区(宏任务队列):主菜、甜点等稍后处理的

什么是宏任务和微任务?

宏任务(主菜)

就像餐厅的主菜,需要更多准备时间:

  • setTimeout/setInterval(定时器)
  • setImmediate(Node.js环境)
  • I/O操作(如读取文件)
  • UI渲染(浏览器中)
  • 整体的script代码

微任务(开胃菜)

像餐厅的餐前小点,快速准备,优先上桌:

  • Promise.then()/.catch()/.finally()
  • process.nextTick()(Node.js环境)
  • MutationObserver(浏览器API)

事件循环的工作流程

让我用更直观的方式展示:

// 事件循环的简化版流程while(true){// 1. 执行当前宏任务执行当前任务();// 2. 执行所有微任务while(微任务队列中有任务){执行微任务();}// 3. 如果需要,渲染UI(浏览器中)// 4. 从宏任务队列取下一个任务开始下一个宏任务();}

实战理解:点餐流程详解

让我们回到最初的例子,看看具体发生了什么:

// 第一轮:执行整体script(这是一个宏任务)console.log('1. 开始点餐');// 直接执行setTimeout(()=>{console.log('6. 20分钟后,主菜来了');},0);// 回调函数放入宏任务队列Promise.resolve().then(()=>{console.log('4. 先上开胃小菜');});// 回调函数放入微任务队列console.log('2. 点完餐了');// 直接执行Promise.resolve().then(()=>{console.log('5. 再上汤品');});// 回调函数放入微任务队列console.log('3. 等待上菜');// 直接执行// 当前宏任务执行完毕!// 开始检查微任务队列...// 第二轮:执行所有微任务// 执行第一个Promise回调:输出"4. 先上开胃小菜"// 执行第二个Promise回调:输出"5. 再上汤品"// 微任务队列清空!// 第三轮:执行下一个宏任务// 执行setTimeout回调:输出"6. 20分钟后,主菜来了"

有趣的进阶例子

console.log('客人入座');setTimeout(()=>console.log('主菜'),0);Promise.resolve().then(()=>{console.log('开胃菜');returnPromise.resolve();}).then(()=>{console.log('汤品');setTimeout(()=>console.log('甜点'),0);});console.log('点餐完成');// 输出顺序:// 客人入座// 点餐完成// 开胃菜// 汤品// 主菜// 甜点

注意:即使setTimeout在微任务中被设置,它仍然是宏任务,要等到下一轮!

为什么这样设计?

JavaScript是单线程的,如果没有这种优先级机制,用户界面会经常"卡住"。微任务机制允许高优先级任务(如Promise回调)插队执行,确保快速响应。

想象一下:如果你在网页上点击一个按钮,它触发的Promise回调(微任务)需要等到所有setTimeout(宏任务)都执行完才能响应,用户体验会有多糟糕!

记忆技巧

  1. 同步代码 > 微任务 > 宏任务
  2. 每个宏任务执行完后,都会清空整个微任务队列
  3. 微任务中可以产生新的微任务,但要注意避免无限循环!

总结

记住这个简单的规律:

  • 宏任务:像餐厅的主菜,按顺序一道道上
  • 微任务:像餐前小点,总是在主菜之前全部上完
  • 事件循环:主厨总是先做完当前菜,然后处理所有小点,再做下一道主菜

理解宏任务和微任务,能帮你避免很多异步编程的坑,写出更可预测的代码。下次看到奇怪的执行顺序时,想想餐厅的比喻吧!

希望这篇文章能帮你理清这个JavaScript的重要概念!如果有疑问或想分享你的理解,欢迎在评论区讨论~ 🍽️✨


小测试:你能预测下面代码的输出顺序吗?

console.log('1');setTimeout(()=>console.log('2'),0);Promise.resolve().then(()=>console.log('3')).then(()=>console.log('4'));console.log('5');

把你的答案写在评论区吧!😉

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/19 21:52:37

Python爬虫实战:利用最新技术从交易所API爬取比特币/加密货币价格与交易数据

引言 在数字货币的浪潮中,获取实时、准确的加密货币数据对于投资者、分析师和开发者至关重要。本文将详细介绍如何使用Python爬虫技术从各大交易所API获取比特币及其他加密货币的价格与交易数据,并进行基本的行情分析。我们将使用最新的Python库和技术栈,包括异步请求、数据…

作者头像 李华
网站建设 2026/2/19 8:45:44

电影推荐系统架构图](https://fakeimg.pl/600x200/ff0000/000?text=SystemArchitecture

hadoop电影推荐系统 大数据电影推荐系统源码 技术栈:javaspringbootlayuihadoop 数据集:豆瓣电影 推荐思路:用户注册登录后浏览电影,对电影进行评分,算法模块定时执行,从mysql读取数据上传到hdfs,并通过执行mapreduce实现的基于用…

作者头像 李华
网站建设 2026/2/21 19:47:09

Kubernetes 环境 NFS 卡死问题排查与解决纪要

Kubernetes 环境 NFS 卡死问题排查与解决纪要 一、事件背景 在 Kubernetes 集群运行过程中,xxxx 命名空间内多个业务 Pod 出现启动异常,部分 Pod 长时间处于 CreateContainerError 或 ContainerCreating 状态,重建 Pod、重启业务均无法恢复。…

作者头像 李华
网站建设 2026/2/22 8:15:56

艾默生EV2000变频器源代码:算法特色显著

艾默生EV2000变频器源代码,算法很有特色蹲在实验室角落拆解EV2000变频器时,意外发现它的电流环控制算法藏着点"野路子"。这货的源代码里有个特别骚的操作——在传统的矢量控制框架下嵌入了动态惯性补偿机制,简单说就是在电机突然加…

作者头像 李华