面试热点: JavaScript 事件循环:Event Loop、宏任务、微任务与执行顺序

发布时间:2026/10/5 16:57:59

面试热点: JavaScript 事件循环:Event Loop、宏任务、微任务与执行顺序 JavaScript Event Loop宏任务、微任务与 async/awaitJavaScript 主线程是单线程执行的也就是说同一时间只能执行一段 JS 代码。但浏览器中又存在很多异步操作例如setTimeout 网络请求 点击事件 Promise如果 JavaScript 每遇到一个异步任务都停下来等待页面就会卡住。因此浏览器会把部分异步任务交给运行环境处理等任务完成后再安排对应的代码重新执行。负责协调这些任务执行顺序的机制就是Event Loop事件循环。一、JavaScript 运行时有哪些部分可以先简单理解成JavaScript 引擎 浏览器 / Node.js 等宿主环境JavaScript 引擎主要负责执行代码例如变量计算 函数调用 Promise async / await浏览器或 Node.js 则提供很多额外能力例如setTimeout setInterval DOM 事件 网络请求 I/O运行过程中主要涉及Call Stack 调用栈 Task Queue 任务队列 Microtask Queue 微任务队列 Event Loop 事件循环普通同步代码会直接进入调用栈执行。二、异步任务怎么执行例如setTimeout(() { console.log(timer) }, 1000) console.log(hello)执行过程可以理解为执行 setTimeout ↓ 浏览器负责计时 ↓ JavaScript 继续执行 ↓ 输出 hello ↓ 计时结束 ↓ setTimeout 回调进入任务队列 ↓ Event Loop 安排回调执行所以最终结果是hello timer三、什么是宏任务常见的宏任务有script 整体代码 setTimeout setInterval I/O 部分事件回调例如setTimeout(() { console.log(宏任务) })setTimeout本身是浏览器或 Node.js 提供的能力不是 JavaScript 语言本身负责计时。可以简单理解为setTimeout ↓ 浏览器 / Node.js 处理 ↓ 回调进入任务队列 ↓ 宏任务所以宏任务通常和定时器、事件、I/O 等宿主环境提供的能力有关。四、什么是微任务常见微任务有Promise.then Promise.catch Promise.finally queueMicrotask MutationObserver async / await 后续代码例如Promise.resolve().then(() { console.log(微任务) }).then()中的回调会进入微任务队列Promise 属于 JavaScript 的 ECMAScript 规范因此很多微任务都和Promise 这套异步机制有关。五、Promise 本身就是微任务吗不是。例如new Promise((resolve) { console.log(1) resolve() }).then(() { console.log(2) })这里console.log(1)是同步执行的。真正属于微任务的是.then(() { console.log(2) })所以要记住Promise 构造函数立即执行then / catch / finally 的回调属于微任务。六、宏任务和微任务有什么区别两者主要有三个区别。1. 来源不同可以粗略理解为宏任务 → 更多来自浏览器 / Node.js → setTimeout、I/O、事件等 微任务 → 很多来自 Promise 机制 → Promise.then、async/await 等但不能绝对理解成宏任务 浏览器 微任务 JS 引擎实际运行时两边会互相配合。2. 队列不同宏任务进入Task Queue 任务队列微任务进入Microtask Queue 微任务队列3. 执行时机不同最重要的规则是当前任务执行完后会先清空所有微任务再执行下一个宏任务。因此执行顺序可以记成当前宏任务 ↓ 执行同步代码 ↓ 清空所有微任务 ↓ 浏览器可能渲染 ↓ 下一个宏任务 ↓ 再次清空微任务最简单的口诀同步代码 → 微任务 → 下一个宏任务七、经典例子console.log(1) setTimeout(() { console.log(2) }, 0) Promise.resolve().then(() { console.log(3) }) console.log(4)最终结果1 4 3 2因为当前这整段script本身可以看作一个宏任务。执行流程是当前宏任务 script ↓ 先执行同步代码 1 4 ↓ 清空微任务 3 ↓ 执行下一个宏任务 setTimeout 2这里要注意不能简单说“微任务一定比宏任务先”。因为当前整段script本身就可以看作一个任务。更准确地说当前任务先执行当前任务结束后微任务优先于下一个宏任务。八、setTimeout(fn, 0) 为什么不是立即执行例如setTimeout(() { console.log(A) }, 0) console.log(B)结果B A因为setTimeout(fn, 0)并不表示立即执行而是表示当时间条件满足后把回调安排到后续任务中等待执行。它仍然要等待当前同步代码执行完成 ↓ 微任务执行完成 ↓ 才有机会执行九、什么是 asyncasync用来声明异步函数。例如async function test() { return 100 }async函数调用后一定返回Promise所以上面的代码可以大致理解成function test() { return Promise.resolve(100) }所以要记住async 函数一定返回 Promise。十、什么是 awaitawait通常写在async函数中async function test() { const result await Promise.resolve(100) console.log(result) }await的作用可以理解为暂停当前 async 函数后续代码等待结果完成后再继续执行。但是await 不会阻塞整个 JavaScript 主线程。例如async function test() { console.log(1) await Promise.resolve() console.log(2) } console.log(3) test() console.log(4)结果3 1 4 2执行过程console.log(3) → 同步执行 test() → 执行 console.log(1) 遇到 await → 当前 async 函数暂停 console.log(4) → 继续同步执行 同步代码结束 → 执行 await 后续代码 console.log(2)所以可以简单记await 前面的代码 → 同步执行 await 后面的代码 → 后续以微任务方式继续执行十一、await 后面不是 Promise 呢例如async function test() { console.log(1) await 100 console.log(2) } test() console.log(3)结果1 3 2虽然100不是 Promise但可以大致理解成await Promise.resolve(100)所以await后面的代码仍然会延后执行。十二、宏任务里面创建微任务例如setTimeout(() { console.log(1) Promise.resolve().then(() { console.log(2) }) console.log(3) }) setTimeout(() { console.log(4) })结果1 3 2 4第一个宏任务执行1 3同时产生微任务2当前宏任务结束后必须先清空微任务2然后才执行下一个宏任务4所以最终1 3 2 4十三、做 Event Loop 题怎么判断以后看到执行顺序题可以按照这个顺序更准确1. 开始执行当前宏任务例如整个 script 2. 执行其中的同步代码 3. 遇到 Promise.then → 放入微任务队列 4. 遇到 setTimeout → 放入后续宏任务队列 5. 当前宏任务执行结束 6. 清空所有微任务 7. 执行下一个宏任务 8. 再次清空微任务 9. 继续循环遇到await时再记住await 前面 → 同步执行 await 后面 → 微任务阶段继续执行总结Event Loop 的作用就是让单线程 JavaScript 能够协调同步代码和异步任务。宏任务通常包括setTimeout setInterval I/O 事件回调微任务通常包括Promise.then Promise.catch Promise.finally queueMicrotask async / await 后续代码两者最重要的区别是来源不同 队列不同 执行时机不同整个 Event Loop 最核心的执行顺序当前任务 ↓ 同步代码 ↓ 清空所有微任务 ↓ 下一个宏任务 ↓ 清空所有微任务 ↓ 继续循环最后记住一句话当前任务先执行当前任务结束后先清空所有微任务再执行下一个宏任务。
延伸阅读

更多相关文章

2026/10/5 16:57:59

『ISOBUS 入门』第 03 节 OSI 模型与 ISO 11783 分册映射

1. 分层与分册的对应 这张图把七层参考模型与分册编号对齐,可以读成四段: OSI 层 对应分册 说明 应用层 ISO 11783-7/8/9/10/12/13/14 农具报文、动力总成、拖拉机 ECU、任务控制器、诊断、文件服务器、顺序控制 表示层 ISO 11783-6/7/11 虚拟终端的对象与数据元呈现规则 会话…

2026/10/5 16:57:59

『ISOBUS 入门』第 14 节 TECU 与 TIM:拖拉机侧的网关与双向协同

拖拉机内部使用的网络协议与农具侧并不相同,农具要读车速、转速、悬挂状态,只能通过一个翻译层。TECU(Tractor ECU,ISO 11783-9)就是这个翻译层:它把拖拉机侧的数据按标准报文发布到 ISOBUS 上,也在需要时把农具侧的请求转回拖拉机内部。 1. 三个等级是「最小消息集」,…

2026/10/5 17:58:01

从零搭建AI工程体系:分层架构、评测与可观测性实战

1. 从零搭建AI工程能力:为什么我劝你别一上来就调包这两年AI应用开发的门槛肉眼可见地降低了,一个刚入门的开发者,装好环境、拿到API Key,半天时间就能跑出一个能对话的Demo。但我带过不少新人,也看过很多团队的项目&a…

2026/10/5 17:58:01

基于Node.js与React构建能思考与行动的AI智能体实战

1. 项目缘起:为什么我要用 paperclip 把 AI 智能体接到真实工作流里第一次看到paperclip这个词,很多人脑子里蹦出来的可能是办公桌上那枚弯弯的金属夹子。但在 Node.js 和 React 的圈子里,它指的是一类很具体的东西:一个把 AI age…

2026/10/5 17:58:01

HSV颜色空间实现红章精准提取与透明PNG生成

1. 这不是“抠图”,是工业级颜色定位与Alpha通道重建 你手头有一张扫描件,白纸黑字,但角落盖着一个鲜红的公章——现在要把它单独抠出来,背景必须是完全透明的PNG,后续要叠在PDF水印层、嵌入电子合同签名区、或者喂给O…

2026/10/5 17:53:01

yolov5单目测距系统毕设拆解:从A4标定到误差量化

简介:这份资源是经导师指导并获98分认可的毕业设计项目,围绕YOLOv5实现单目测距系统,面向计算机相关专业正在做毕设、课程设计或期末大作业的学生,也适合需要项目实战练习的学习者。项目已通过严格调试,可直接作为毕设…

2026/10/5 17:53:01

AMESim柱塞泵建模全流程:从HCD库到Simulink联合仿真

做液压仿真这行,绕不开柱塞泵,更绕不开AMESim。我早些年刚接触AMESim的时候,光是想把一台斜盘式轴向柱塞泵的模型搭出来,就折腾了将近两周。看论文觉得原理都懂,打开软件却不知道从哪个库拖元件、参数填多少、为什么一…

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/5 17:38:27

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑