javascript 的 event loop 是单线程模型下实现异步非阻塞的关键机制,它通过调度宏任务与微任务、委托耗时操作给宿主环境、在调用栈空闲时按优先级执行回调,确保同步代码优先、ui 不卡顿、dom 操作安全且可预测。

JavaScript 的 Event Loop 是单线程模型下实现异步非阻塞的关键机制。它不改变“只有一个主线程”的事实,而是通过调度策略让异步任务不抢占执行权,从而避免阻塞。
单线程 ≠ 只能同步执行
JavaScript 引擎本身只有一条调用栈,所有同步代码按顺序压入、执行、清空。但浏览器或 Node.js 运行时提供了额外能力:定时器、网络请求、DOM 事件等,这些操作交由底层线程(如 Web APIs)处理,JS 主线程无需等待结果,继续往下跑。
- 同步代码立即执行,占据调用栈
- 异步操作(如 setTimeout、fetch、addEventListener)被委托给宿主环境,主线程立刻返回
- 当异步任务完成,回调函数被放入对应的任务队列(宏任务或微任务),等待主线程空闲时由 Event Loop 拿出执行
Event Loop 的实际调度节奏
Event Loop 不是轮询,而是一个持续循环的协调者:每次循环先清空当前所有微任务(如 Promise.then 回调),再从宏任务队列取一个任务执行(如 setTimeout 回调)。这个顺序决定了真实执行时机。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 宏任务(Macrotask):setTimeout、setInterval、I/O、UI 渲染等,每次循环只执行一个
- 微任务(Microtask):Promise.then/catch/finally、queueMicrotask、MutationObserver,每次宏任务后全部执行完
- 例如:console.log('1'); Promise.resolve().then(() => console.log('2')); setTimeout(() => console.log('3'), 0); console.log('4'); 输出为 1 → 4 → 2 → 3
非阻塞的本质是“不等”
非阻塞不是靠多线程并发,而是靠“委托+回调+排队”。主线程永远优先跑完同步逻辑,把耗时动作甩给系统级模块,自己不卡住,也不主动查状态,只等通知——通知来了就按优先级插入执行流。
- 没有 callback 或 Promise 的异步操作(比如纯 setTimeout)只是延后执行,不产生实际 I/O
- 真正非阻塞体现在 I/O 类操作(如 fetch、fs.readFile):JS 发起请求后立刻继续,结果由底层完成后再触发 Promise resolve 或回调
- 用户交互(点击、滚动)也走同一套机制:事件被加入宏任务队列,等主线程腾出手才响应
为什么必须靠 Event Loop 而不是直接开线程
因为 DOM 操作不可并发。如果 JS 支持多线程,两个线程同时修改同一个 div,浏览器无法确定最终状态。单线程 + Event Loop 保证了所有变更都串行经过调用栈,渲染和逻辑始终一致。
- 所有 DOM 更新、样式计算、布局、绘制都在一次宏任务结束后触发(浏览器渲染帧)
- 微任务在渲染前执行,适合做状态修正(如 Vue nextTick、React flushSync 后的更新)
- 这种设计让开发者面对的是可预测的执行顺序,而不是竞态条件和锁机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










