258 The Event Loop in Practice

一、视频基础信息

  1. 所属课程:Udemy 排名第一的 JavaScript 课程《2023 最新完整 JavaScript 课程 从入门到精通 – 通过项目、挑战和理论掌握 JS》(中英文字幕版·下)
  2. 视频定位:该课程第 42 集,聚焦 JavaScript 事件循环(Event Loop)的实践应用,是异步 JavaScript 学习的核心实操内容
  3. 课程规模:课程合集共 98 集,本集是理解事件循环机制从理论到实践的关键过渡内容

二、核心知识:事件循环实践核心示例

2.1 示例代码构建

视频通过编写以下核心代码,引出事件循环执行顺序的思考,代码逻辑拆解如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1. 同步代码:第一次打印“测试”
console.log("测试1");

// 2. 宏任务:零秒计时器(回调函数打印计时器内容)
setTimeout(() => {
console.log("零秒计时器回调");
}, 0);

// 3. 微任务:立即 resolved 的 Promise(回调函数打印 Promise 结果)
Promise.resolve("Promise 成功结果").then((res) => {
console.log(res);
});

// 4. 同步代码:第二次打印“测试”
console.log("测试2");

2.2 关键问题提出

基于上述代码,视频引导观众思考:4 条打印语句在控制台的输出顺序是什么?
(建议先暂停视频独立分析,再对照后续逻辑验证)

三、核心逻辑:事件循环执行顺序分析

3.1 第一步:明确任务类型分类

事件循环中,JavaScript 任务分为两类,优先级差异是执行顺序的核心决定因素:

任务类型 定义 本示例中的对应任务
同步任务 主线程直接执行,无需进入任务队列的代码 两次 console.log("测试")
微任务(Microtask) 优先级高于宏任务,同步任务执行完后立即执行,需进入“微任务队列” Promise.then() 回调
宏任务(Macrotask) 优先级低于微任务,微任务队列清空后才执行,需进入“宏任务队列” setTimeout 回调(即使延迟 0ms)

3.2 第二步:执行顺序推导(含例题验证)

例题 1:基于上述代码,推导输出顺序

  1. 第一步:执行同步任务
    主线程优先执行所有同步代码,因此先输出:

    1
    2
    测试1
    测试2
  2. 第二步:清空微任务队列
    同步任务执行完毕后,主线程会先检查微任务队列。本示例中,Promise.resolve() 立即 resolved,其 then 回调已进入微任务队列,因此执行微任务,输出:

    1
    Promise 成功结果
  3. 第三步:执行宏任务队列
    微任务队列清空后,主线程才检查宏任务队列。setTimeout(..., 0) 的回调虽设置延迟 0ms,但仍属于宏任务,此时才执行,输出:

    1
    零秒计时器回调
  4. 最终输出顺序结论
    测试1 → 测试2 → Promise 成功结果 → 零秒计时器回调

四、拓展实验:微任务耗时对宏任务的影响

4.1 实验代码构建

为验证“微任务优先级高于宏任务”的实际影响,视频新增含耗时操作的微任务,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log("测试1");

// 宏任务:零秒计时器
setTimeout(() => {
console.log("零秒计时器回调");
}, 0);

// 微任务:含耗时循环的 Promise(模拟微任务执行耗时)
Promise.resolve("Promise 成功结果").then((res) => {
console.log(res);
// 模拟耗时操作:循环 1 亿次(阻塞主线程)
for (let i = 0; i < 100000000; i++) {}
});

console.log("测试2");

4.2 实验现象与结论

例题 2:分析上述代码的执行现象

  1. 现象:运行代码后,“零秒计时器回调”会明显延迟输出,需等待微任务中的 1 亿次循环执行完毕后才出现
  2. 结论
    • JavaScript 计时器(如 setTimeout)无法保证“精确延迟执行”,其回调的执行依赖宏任务队列的调度
    • 若微任务执行耗时较长,会阻塞后续宏任务的执行,导致宏任务“延迟触发”,进一步印证“微任务队列优先级高于宏任务队列”的核心规则

五、视频总结与后续预告

5.1 核心知识点总结

  1. 事件循环执行流程:同步任务 → 清空微任务队列 → 执行宏任务队列(循环)
  2. 任务优先级:同步任务 > 微任务(如 Promise.then)> 宏任务(如 setTimeout)
  3. 关键注意点:setTimeout(..., 0) 仅表示“尽快执行”,不代表“零秒后立即执行”,需受微任务执行情况影响

5.2 后续内容预告

下一节视频将回归异步 JavaScript 实践,从基础开始讲解“如何手动创建 Promise”,进一步深入 Promise 的底层逻辑与应用场景。