浏览器中的Event Loop事件循环是前端面试几乎必问的知识点2026 年大厂字节、美团、腾讯、阿里、京东、小红书等通常不仅会问概念还会让你分析代码执行顺序。一、为什么需要 Event LoopJavaScript 是单线程的。也就是说一次只能执行一个任务如果遇到耗时操作网络请求、定时器、DOM事件不能一直阻塞主线程因此浏览器设计了Call Stack调用栈 ↓ Web APIs ↓ Task Queue任务队列 ↓ Event Loop事件循环流程执行同步代码 ↓ 调用异步API ↓ 异步完成进入队列 ↓ 等待调用栈为空 ↓ Event Loop 把任务放回调用栈二、浏览器线程模型浏览器并不是只有一个线程。例如 ChromeBrowser Process │ ├── GUI Render ├── JS Engine ├── Timer ├── Network ├── EventJavaScript只有一个主线程但是setTimeout fetch XMLHttpRequest DOM事件 都是浏览器其它线程完成例如console.log(1) setTimeout((){ console.log(2) },1000) console.log(3)执行过程JS线程 ↓ console.log(1) ↓ setTimeout ↓ 浏览器Timer线程开始计时 ↓ console.log(3) ↓ 同步结束 ↓ 1秒后Timer线程通知 ↓ 加入Task Queue ↓ Event Loop ↓ console.log(2)输出1 3 2三、调用栈Call Stack例如functiona(){b()}functionb(){c()}functionc(){console.log(hello)}a()调用栈变化空 ↓ a ↓ a b ↓ a b c ↓ 执行完成 ↓ 空只要调用栈不为空Event Loop 不会取任务四、宏任务MacroTask浏览器里的宏任务包括script setTimeout setInterval requestAnimationFrame渲染前 I/O MessageChannel例如setTimeout((){console.log(1)})setTimeout((){console.log(2)})进入MacroTask Queue ↓ 1 ↓ 2依次执行。五、微任务MicroTask微任务优先级比宏任务高。常见Promise.then Promise.catch Promise.finally queueMicrotask MutationObserver例如Promise.resolve().then((){console.log(1)})console.log(2)输出2 1因为同步 ↓ 微任务六、Event Loop 执行流程浏览器 Event Loop执行一个宏任务 ↓ 执行所有微任务 ↓ 渲染页面 ↓ 执行下一个宏任务 ↓ 执行所有微任务 ↓ 渲染页面 循环记住MacroTask ↓ 全部 MicroTask ↓ Render ↓ MacroTask七、经典面试题①console.log(1)setTimeout((){console.log(2)})Promise.resolve().then((){console.log(3)})console.log(4)执行同步1 4微任务3宏任务2最终1 4 3 2八、经典面试题②console.log(1)setTimeout((){console.log(2)Promise.resolve().then((){console.log(3)})})Promise.resolve().then((){console.log(4)})console.log(5)同步1 5微任务4宏任务2该宏任务里的微任务3结果1 5 4 2 3九、经典面试题③console.log(A)setTimeout((){console.log(B)},0)Promise.resolve().then((){console.log(C)}).then((){console.log(D)})console.log(E)同步A E微任务C D宏任务B结果A E C D B十、async / await 与 Event Loop例如asyncfunctiontest(){console.log(1)awaitPromise.resolve()console.log(2)}console.log(3)test()console.log(4)执行同步3 1 4await后面的代码会作为微任务继续执行2结果3 1 4 2可以理解为awaitPromise.resolve()↓ Promise.resolve().then((){...})十一、2026 面试高频总结牢记下面几个规则即可应对绝大多数 Event Loop 题目先执行所有同步代码当前宏任务。当前宏任务结束后立即清空所有微任务队列包括微任务中新产生的微任务。浏览器有机会进行页面渲染。开始执行下一个宏任务如setTimeout回调。重复以上流程。优先级可以记成同步代码 ↓ 微任务Promise.then、queueMicrotask、await 后续代码等 ↓ 页面渲染浏览器 ↓ 宏任务setTimeout、setInterval 等面试答题模板1 分钟JavaScript 是单线程运行的。浏览器通过 Event Loop 协调同步任务和异步任务的执行。同步代码先进入调用栈执行异步操作由浏览器相关线程处理完成后对应的回调进入任务队列。事件循环会在当前宏任务执行结束且调用栈为空时先清空所有微任务队列再进入下一轮宏任务。在浏览器中一般每轮事件循环都会在宏任务和微任务处理完成后给渲染线程一次更新页面的机会。因此通常遵循“同步代码 → 微任务 →渲染→ 下一个宏任务”的执行顺序。这样既保证了单线程模型又能高效处理异步任务。
Event Loop(事件循环)
发布时间:2026/7/7 7:24:32
浏览器中的Event Loop事件循环是前端面试几乎必问的知识点2026 年大厂字节、美团、腾讯、阿里、京东、小红书等通常不仅会问概念还会让你分析代码执行顺序。一、为什么需要 Event LoopJavaScript 是单线程的。也就是说一次只能执行一个任务如果遇到耗时操作网络请求、定时器、DOM事件不能一直阻塞主线程因此浏览器设计了Call Stack调用栈 ↓ Web APIs ↓ Task Queue任务队列 ↓ Event Loop事件循环流程执行同步代码 ↓ 调用异步API ↓ 异步完成进入队列 ↓ 等待调用栈为空 ↓ Event Loop 把任务放回调用栈二、浏览器线程模型浏览器并不是只有一个线程。例如 ChromeBrowser Process │ ├── GUI Render ├── JS Engine ├── Timer ├── Network ├── EventJavaScript只有一个主线程但是setTimeout fetch XMLHttpRequest DOM事件 都是浏览器其它线程完成例如console.log(1) setTimeout((){ console.log(2) },1000) console.log(3)执行过程JS线程 ↓ console.log(1) ↓ setTimeout ↓ 浏览器Timer线程开始计时 ↓ console.log(3) ↓ 同步结束 ↓ 1秒后Timer线程通知 ↓ 加入Task Queue ↓ Event Loop ↓ console.log(2)输出1 3 2三、调用栈Call Stack例如functiona(){b()}functionb(){c()}functionc(){console.log(hello)}a()调用栈变化空 ↓ a ↓ a b ↓ a b c ↓ 执行完成 ↓ 空只要调用栈不为空Event Loop 不会取任务四、宏任务MacroTask浏览器里的宏任务包括script setTimeout setInterval requestAnimationFrame渲染前 I/O MessageChannel例如setTimeout((){console.log(1)})setTimeout((){console.log(2)})进入MacroTask Queue ↓ 1 ↓ 2依次执行。五、微任务MicroTask微任务优先级比宏任务高。常见Promise.then Promise.catch Promise.finally queueMicrotask MutationObserver例如Promise.resolve().then((){console.log(1)})console.log(2)输出2 1因为同步 ↓ 微任务六、Event Loop 执行流程浏览器 Event Loop执行一个宏任务 ↓ 执行所有微任务 ↓ 渲染页面 ↓ 执行下一个宏任务 ↓ 执行所有微任务 ↓ 渲染页面 循环记住MacroTask ↓ 全部 MicroTask ↓ Render ↓ MacroTask七、经典面试题①console.log(1)setTimeout((){console.log(2)})Promise.resolve().then((){console.log(3)})console.log(4)执行同步1 4微任务3宏任务2最终1 4 3 2八、经典面试题②console.log(1)setTimeout((){console.log(2)Promise.resolve().then((){console.log(3)})})Promise.resolve().then((){console.log(4)})console.log(5)同步1 5微任务4宏任务2该宏任务里的微任务3结果1 5 4 2 3九、经典面试题③console.log(A)setTimeout((){console.log(B)},0)Promise.resolve().then((){console.log(C)}).then((){console.log(D)})console.log(E)同步A E微任务C D宏任务B结果A E C D B十、async / await 与 Event Loop例如asyncfunctiontest(){console.log(1)awaitPromise.resolve()console.log(2)}console.log(3)test()console.log(4)执行同步3 1 4await后面的代码会作为微任务继续执行2结果3 1 4 2可以理解为awaitPromise.resolve()↓ Promise.resolve().then((){...})十一、2026 面试高频总结牢记下面几个规则即可应对绝大多数 Event Loop 题目先执行所有同步代码当前宏任务。当前宏任务结束后立即清空所有微任务队列包括微任务中新产生的微任务。浏览器有机会进行页面渲染。开始执行下一个宏任务如setTimeout回调。重复以上流程。优先级可以记成同步代码 ↓ 微任务Promise.then、queueMicrotask、await 后续代码等 ↓ 页面渲染浏览器 ↓ 宏任务setTimeout、setInterval 等面试答题模板1 分钟JavaScript 是单线程运行的。浏览器通过 Event Loop 协调同步任务和异步任务的执行。同步代码先进入调用栈执行异步操作由浏览器相关线程处理完成后对应的回调进入任务队列。事件循环会在当前宏任务执行结束且调用栈为空时先清空所有微任务队列再进入下一轮宏任务。在浏览器中一般每轮事件循环都会在宏任务和微任务处理完成后给渲染线程一次更新页面的机会。因此通常遵循“同步代码 → 微任务 →渲染→ 下一个宏任务”的执行顺序。这样既保证了单线程模型又能高效处理异步任务。