在 js 中,事件循环(Event Loop)是一个极其重要的概念,它确保了非阻塞的异步编程模型。理解事件循环不仅有助于我们编写更高效的代码,还能帮助我们更好地调试和优化应用程序。
什么是事件循环?
事件循环是 JavaScript 的一种控制结构,它允许你执行代码、收集事件并执行网络请求。在 JavaScript 的背景下,事件循环负责管理执行栈和消息队列之间的交互,从而实现非阻塞的异步操作。
js 的执行模型
javaScript 是一种单线程语言,这意味着它一次只能执行一个任务。为了实现异步操作,JavaScript 使用了执行栈(Call Stack)和消息队列(Message Queue)。
执行栈(Call Stack)
执行栈是一个后进先出的数据结构,当一个函数被调用时,它会被推入执行栈,执行完后会被弹出。(可以抽象的理解为打开抽屉,然后往抽屉里一本一本放书,拿出的时候,后放进去的书反而先拿出来)简单来说,执行栈管理着当前正在执行的代码。
消息队列(Message Queue)
消息队列则存放着待处理的事件和回调函数。当某个事件发生(例如点击按钮、网络请求完成等),相应的回调函数会被推入消息队列。当执行栈为空时,事件循环会从消息队列中取出函数并执行。
事件循环的工作机制
事件循环的基本流程如下:
- 执行栈为空:当执行栈为空时,事件循环会检查消息队列。
- 检查消息队列:如果消息队列中有待处理的事件,事件循环会将队列中的第一个事件取出,推入执行栈并执行。
- 重复以上步骤:执行完事件之后,事件循环又会检查消息队列,直到所有事件都被处理完。
示例说明
让我们通过一个简单的例子来更好地理解事件循环。
1 | console.log("Start"); // 1 |
执行顺序分析
console.log("Start")
被推入执行栈并立即执行,输出Start
。setTimeout
被调用,将回调函数加入到宏任务队列(Message Queue),但不会立即执行。Promise.resolve().then(...)
被调用,将回调函数加入微任务队列(Microtask Queue)。console.log("End")
被推入执行栈并执行,输出End
。- 执行栈此时为空,事件循环会首先检查微任务队列,并发现有待执行的 Promise 回调,输出
Promise
。 - 执行完微任务之后,事件循环再检查宏任务队列,发现
setTimeout
的回调,输出Timeout
。
输出顺序
因此,最终的输出顺序为:
1 | Start |
微任务与宏任务
在 JavaScript 中,事件循环中有两个任务队列:微任务队列和宏任务队列。微任务队列的优先级高于宏任务队列。常见的微任务有 Promise
的回调,宏任务则包括 setTimeout
和 setInterval
。
ok这样我们就理解了事件循环机制了。


