1. 为什么需要理解事件循环机制
第一次遇到JavaScript异步问题的时候,我正在开发一个电商网站的购物车功能。当用户点击"立即购买"按钮时,需要先检查库存,然后更新购物车,最后跳转到结算页面。我按照同步思维写了这样的代码:
javascript复制checkInventory();
updateCart();
redirectToCheckout();
结果页面直接跳转,库存和购物车根本没更新!这个bug让我意识到,如果不彻底理解JavaScript的事件循环机制,就永远写不出正确的异步代码。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 事件循环的核心组成
2.1 调用栈(Call Stack)
调用栈是JavaScript执行同步代码的地方。当我调试上面那个bug时,在Chrome DevTools中看到的调用栈是这样的:
- button.click()
- handlePurchase()
- checkInventory()
- updateCart()
- redirectToCheckout()
调用栈遵循后进先出原则,就像一摞盘子,最后放上去的会最先被拿走。
2.2 任务队列(Task Queue)
任务队列分为两种:
- 宏任务队列:包含setTimeout、setInterval、I/O、UI渲染等
- 微任务队列:包含Promise.then、MutationObserver等
我在项目中曾遇到一个典型问题:一个复杂的表单提交操作,需要先验证数据,然后发送请求,最后更新UI。最初我这样写:
javascript复制validateForm();
fetch('/submit', { method: 'POST' })
.then(updateUI);
showSuccessMessage();
结果success消息在UI更新前就显示了!这是因为Promise.then属于微任务,而直接执行的showSuccessMessage是同步代码。
3. 事件循环的运行机制
3.1 完整的事件循环流程
- 执行同步代码,填充调用栈
- 遇到异步操作时:
- Web API处理定时器、网络请求等
- 完成后将回调放入任务队列
- 调用栈清空后
