1. 基本概念

事件循环是JavaScript实现异步编程的核心机制,它负责协调主线程和任务队列,确保JavaScript代码能够非阻塞地执行。

2. 核心组成部分

2.1 调用栈(Call Stack)

  • 用于存储正在执行的函数调用
  • 遵循后进先出(LIFO)原则
  • 当函数执行完毕时,会从栈顶弹出

2.2 任务队列(Task Queue)

  • 宏任务队列(Macro Task Queue):setTimeout、setInterval、setImmediate、I/O、UI渲染等
  • 微任务队列(Micro Task Queue):Promise.then/catch/finally、process.nextTick、MutationObserver等

3. 事件循环执行流程

1. 执行同步代码(调用栈)
2. 检查微任务队列,执行所有微任务
3. 执行一个宏任务
4. 重复步骤2-3

4. 详细执行顺序

console.log('1'); // 同步代码
 
setTimeout(() => {
    console.log('2'); // 宏任务
}, 0);
 
Promise.resolve().then(() => {
    console.log('3'); // 微任务
});
 
console.log('4'); // 同步代码
 
// 输出顺序:1, 4, 3, 2

5. 关键特点

5.1 微任务优先级高于宏任务

  • 每执行完一个宏任务后,会立即检查并执行所有微任务
  • 微任务会在下一个宏任务之前执行

5.2 同类型任务按顺序执行

  • 宏任务按先进先出(FIFO)顺序执行
  • 微任务按先进先出(FIFO)顺序执行

7. 常见面试题示例

7.1 经典题目

console.log('start');
 
setTimeout(() => {
    console.log('timeout1');
    Promise.resolve().then(() => {
        console.log('promise1');
    });
}, 0);
 
Promise.resolve().then(() => {
    console.log('promise2');
    setTimeout(() => {
        console.log('timeout2');
    }, 0);
});
 
console.log('end');
 
// 输出:start, end, promise2, timeout1, promise1, timeout2