事件循环(Event Loop)是JavaScript运行时(例如浏览器或Node.js)的一种机制,用于处理异步编程。它允许非阻塞操作,即使在某些任务需要等待(如网络请求或定时器),JavaScript也可以继续执行其他代码。
事件循环的基本概念
-
调用栈(Call Stack):
- JavaScript是一门单线程语言,这意味着它一次只能执行一个任务。
- 当函数被调用时,它会被加入到调用栈中。
- 函数执行完毕后,会从调用栈中弹出。
-
任务队列(Task Queue):
- 异步操作完成后会将其回调函数放入任务队列中。
- 任务队列分为宏任务(macro-task)和微任务(micro-task)。
宏任务和微任务
- 宏任务(Macro-task):包括
setTimeout
、setInterval
、setImmediate
(Node.js特有)、I/O操作、UI渲染等。 - 微任务(Micro-task):包括
Promise
的回调函数、MutationObserver
、process.nextTick
(Node.js特有)等。
事件循环的工作过程
- 执行同步代码:从调用栈中依次执行同步代码,这些代码在一个事件循环周期内执行。
- 检查微任务队列:在调用栈为空时,事件循环检查并执行微任务队列中的所有微任务。微任务队列优先于宏任务队列执行。
- 执行宏任务:从宏任务队列中取出第一个任务并执行,通常会再次进入调用栈执行同步代码。
- 重复以上步骤:事件循环重复以上步骤,不断处理调用栈和任务队列中的任务。
示例解释
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('promise1');
}).then(() => {
console.log('promise2');
});
console.log('script end');
执行流程如下:
console.log('script start')
被执行并打印:"script start"。setTimeout
回调被注册并放入宏任务队列。Promise.resolve().then
回调被注册并放入微任务队列。console.log('script end')
被执行并打印:"script end"。- 调用栈为空,开始检查微任务队列。
- 执行第一个微任务
promise1
回调,打印:"promise1"。 promise2
回调被注册并放入微任务队列。- 执行第二个微任务
promise2
回调,打印:"promise2"。
- 执行第一个微任务
- 微任务队列为空,开始执行宏任务队列中的任务。
- 执行
setTimeout
回调,打印:"setTimeout"。
- 执行
最终输出顺序为:
script start
script end
promise1
promise2
setTimeout
事件循环在浏览器和Node.js中的差异
- 浏览器:事件循环主要用于处理用户交互、DOM操作、网络请求等。
- Node.js:事件循环用于处理I/O操作、定时器、回调等,分为多个阶段(timers、pending callbacks、poll、check、close callbacks等)。
事件循环使得JavaScript可以高效地处理异步操作,通过将异步任务分配到任务队列,并在主线程空闲时进行处理,确保了非阻塞的执行模型。
标签:setTimeout,console,script,队列,任务,循环,事件,执行 From: https://blog.csdn.net/m0_73882020/article/details/140854918