JavaScript事件循环是单线程通过调用栈、宏任务队列和微任务队列协作实现异步非阻塞的核心机制;同步代码入栈执行,异步回调由Web API处理后按宏/微任务优先级进入对应队列,每轮先清空微任务再取一个宏任务。

JavaScript 的事件循环(Event Loop)是它实现异步非阻塞行为的核心机制,不是靠多线程,而是靠单线程 + 任务队列 + 调用栈协作完成的。
调用栈与任务的执行顺序
JS 是单线程语言,所有同步代码都在一个调用栈(Call Stack)中按顺序执行。遇到函数调用就压栈,返回就出栈。一旦栈空了,引擎不会停,而是去检查有没有待处理的“任务”。
- 同步任务(如
console.log()、普通函数调用)直接进栈执行 -
异步任务(如
setTimeout、fetch、用户点击)不会卡住主线程,而是交由 Web API(浏览器)或 Node.js 环境处理 - 等异步操作完成,Web API 把对应的回调函数推入任务队列(Task Queue),等待调用栈空闲
宏任务与微任务的区别
任务队列其实分两类:宏任务(macrotask)和微任务(microtask),它们的执行优先级不同。
-
宏任务:包括
setTimeout、setInterval、I/O、UI 渲染、script标签整体等 -
微任务:包括
Promise.then/catch/finally、MutationObserver、queueMicrotask() - 每次调用栈清空后,先执行所有当前轮次的微任务(直到微任务队列为空),再取一个宏任务执行
这就是为什么 Promise 总比 setTimeout 先输出——它属于更高优先级的微任务队列。
立即学习“Java免费学习笔记(深入)”;
一套面向小企业用户的企业网站程序!功能简单,操作简单。实现了小企业网站的很多实用的功能,如文章新闻模块、图片展示、产品列表以及小型的下载功能,还同时增加了邮件订阅等相应模块。公告,友情链接等这些通用功能本程序也同样都集成了!同时本程序引入了模块功能,只要在系统默认模板上创建模块,可以在任何一个语言环境(或任意风格)的适当位置进行使用!
事件循环的基本流程
用伪代码描述一次循环:
- 执行一个宏任务(比如主 script 或某个
setTimeout回调) - 执行过程中遇到同步代码 → 直接入栈运行;遇到 Promise → 立即执行 executor,then 注册进微任务队列;遇到
setTimeout→ 交由浏览器延时,到期后推入宏任务队列 - 宏任务执行完,检查微任务队列 → 逐个执行,直到清空
- 渲染(可选,浏览器环境下)→ UI 更新
- 从宏任务队列取下一个任务,重复上述过程
一个典型例子帮你理清顺序
看这段代码:
console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4);
输出顺序是:1 → 4 → 3 → 2。因为:
-
1和4是同步,立刻执行 -
Promise.then是微任务,排在当前宏任务结束后、下个宏任务前 -
setTimeout是宏任务,要等本轮全部微任务走完,再等下一轮循环才执行
基本上就这些。理解事件循环不靠死记,关键是分清“谁进栈、谁进哪个队列、谁先被调度”。多写几个带 setTimeout 和 Promise 的小例子跑一跑,节奏就自然了。










