事件循环(Event Loop) 是 JavaScript 运行时环境(如浏览器或 Node.js)中用于处理异步操作的核心机制。它使得 JavaScript 能够在单线程环境中高效地处理多个任务,包括 I/O 操作、定时器、用户交互等。
事件循环的基本概念
-
单线程:JavaScript 是单线程的,意味着它一次只能执行一个任务。
-
任务队列:异步操作完成后,其回调函数会被放入任务队列中等待执行。
-
事件循环:事件循环不断地检查调用栈(Call Stack)和任务队列,当调用栈为空时,将任务队列中的任务推入调用栈执行。
事件循环的工作流程
-
执行同步代码:所有同步代码依次执行,形成一个调用栈。
-
处理异步任务:遇到异步操作(如
setTimeout
、Promise
、fetch
等),将其交给相应的 Web API 或线程池处理。 -
任务队列:异步操作完成后,其回调函数被放入任务队列中。
-
事件循环:当调用栈为空时,事件循环从任务队列中取出任务并推入调用栈执行。
任务队列的类型
-
宏任务队列(MacroTask Queue):
-
setTimeout
-
setInterval
-
setImmediate
(Node.js) -
I/O 操作
-
UI 渲染(浏览器)
-
-
微任务队列(MicroTask Queue):
-
Promise.then
-
Promise.catch
-
Promise.finally
-
MutationObserver
(浏览器) -
process.nextTick
(Node.js)
-
事件循环的执行顺序
-
执行同步代码:所有同步代码依次执行。
-
执行微任务:调用栈为空后,执行所有微任务队列中的任务。
-
执行宏任务:每次执行一个宏任务后,再次检查微任务队列并执行所有微任务。
-
重复:重复上述步骤,直到所有任务队列为空。
示例
console.log('Start');setTimeout(() => {console.log('Timeout');
}, 0);Promise.resolve().then(() => {console.log('Promise');
});console.log('End');
输出顺序
Start
End
Promise
Timeout
解释
-
同步代码:
console.log('Start')
和console.log('End')
依次执行。 -
微任务:
Promise.resolve().then(...)
的回调被放入微任务队列,在同步代码执行完后立即执行。 -
宏任务:
setTimeout
的回调被放入宏任务队列,在微任务执行完后执行。
总结
-
事件循环 是 JavaScript 处理异步操作的核心机制。
-
任务队列 分为宏任务队列和微任务队列。
-
执行顺序:同步代码 -> 微任务 -> 宏任务 -> 微任务 -> ...
-
理解事件循环有助于编写高效且可预测的异步代码。
事件循环机制使得 JavaScript 能够在单线程环境中高效地处理多个任务,是现代 JavaScript 开发中的重要概念。