JavaScript事件循环是异步非阻塞核心机制,按“执行宏任务→清空微任务队列→可选UI渲染→取下一宏任务”流程调度;宏任务(如setTimeout)每轮一个,微任务(如Promise.then)在宏任务后全部执行完毕。

JavaScript 的事件循环(Event Loop)是它实现异步非阻塞特性的核心机制,负责协调执行栈、任务队列(宏任务与微任务)以及调用 API 的时机。它不“管理”队列本身,而是按固定规则轮询和调度队列中的任务。
宏任务与微任务的区分
事件循环把异步任务分为两类:
-
宏任务(Macrotask):包括整体脚本、
setTimeout、setInterval、setImmediate(Node.js)、I/O 回调、UI 渲染等;每次事件循环只执行一个宏任务。 -
微任务(Microtask):包括
Promise.then/catch/finally、MutationObserver、queueMicrotask();在每个宏任务执行完后,会清空整个微任务队列(即全部执行完,直到为空)。
事件循环的基本流程
一次完整的循环步骤如下:
- 执行当前宏任务(如主脚本或某个定时器回调)
- 执行过程中遇到
Promise等,将对应的then回调推入微任务队列 - 宏任务执行完毕,立即执行所有排队的微任务(逐个取出并执行,期间新加入的微任务也会被本轮执行)
- 微任务队列清空后,浏览器可能进行一次 UI 渲染(如果需要)
- 从宏任务队列中取出下一个任务(如 setTimeout 回调),开始下一轮
任务队列不是先进先出的简单队列
宏任务队列实际由多个来源组成,优先级不同:
立即学习“Java免费学习笔记(深入)”;
- HTML 规范定义了不同类型的任务源(如 DOM 操作、网络、定时器),但具体执行顺序由宿主环境决定
-
setTimeout(fn, 0)并不意味着立刻执行,而是“至少延迟 0ms”,实际要等当前宏任务 + 所有微任务完成,并等到下一次事件循环才可能执行 - 微任务队列始终具有更高优先级——它总是在宏任务之间插入执行,且不会被渲染或 I/O 中断
常见误区提醒
几个容易混淆的点:
-
Promise.resolve().then()是微任务,setTimeout(() => {}, 0)是宏任务,二者嵌套时微任务总比同层宏任务先运行 - 多个
Promise.then链式调用会依次加入微任务队列,按注册顺序执行 - Node.js 中还有
process.nextTick(),它的优先级高于所有微任务(包括Promise),但仅限 Node 环境











