【前端每天一题】🔥 第3题 事件循环 20 道经典面试题(附详细答案)

事件循环(Event Loop) - 前端面试核心题

这是前端面试最重要、最核心、最容易区分候选人水平的题之一。

0. 面试"标准一句话"版本

JS 是单线程语言,事件循环(Event Loop)负责协调同步任务、微任务(Promise)、宏任务(setTimeout等)的执行顺序;同步任务优先执行,之后每一轮循环都会先清空微任务队列,再执行一个宏任务,如此循环。

如果一分钟要答完,这样非常稳。

1. 为什么需要事件循环?(面试官很爱问)

因为:

  • JS 是单线程
  • 但浏览器要同时处理 UI 渲染、定时器、网络、用户输入等

所以必须用一个调度机制来"异步执行任务" → 这就是事件循环(Event Loop)

你的回答要提到"避免阻塞 UI" = 加分。

2. 事件循环的流程(核心逻辑)

事件循环的本质是:

同步任务 → 微任务 → 宏任务 → 微任务 → 宏任务 → ...

通常流程:

  1. 执行同步任务(栈)
  2. 清空所有微任务队列(microtask queue)
  3. 执行一个宏任务(macrotask queue)
  4. 再次清空微任务
  5. 再执行下一个宏任务
  6. 无限循环(Loop)

3. 宏任务 vs 微任务(必须背)

微任务(microtasks)

  • Promise.then/catch/finally
  • MutationObserver
  • queueMicrotask()
  • (Node)process.nextTick

宏任务(macrotasks)

  • setTimeout
  • setInterval
  • setImmediate(Node)
  • I/O 回调
  • UI 渲染事件
  • MessageChannel

口诀:微任务优先,Promise 是微任务。

4. 最经典的事件循环例题(90% 的面试官会问)

题 A:

javascript 复制代码
console.log(1);

setTimeout(() => console.log(2));

Promise.resolve().then(() => console.log(3));

console.log(4);

执行顺序:

复制代码
1
4
3
2

解释:

  • 同步:1 → 4
  • 微任务(then):3
  • 宏任务(setTimeout):2

题 B:Promise 中的多层微任务

javascript 复制代码
Promise.resolve()
  .then(() => {
    console.log(1);
    Promise.resolve().then(() => console.log(2));
  })
  .then(() => console.log(3));

输出顺序:

复制代码
1
2
3

解释: 每执行完一个 then,产生的微任务会加入同一轮的微任务队列中。

题 C:超级经典陷阱(setTimeout vs Promise)

javascript 复制代码
console.log(1);

setTimeout(() => {
  console.log(2);
}, 0);

Promise.resolve().then(() => {
  console.log(3);
});

console.log(4);

输出仍然是:

复制代码
1
4
3
2

哪怕 setTimeout 是 0,也永远比 Microtask 晚。

5. Event Loop 与浏览器渲染(加分项)

每一轮宏任务结束后,浏览器通常会进行:

  • 页面重绘(paint)
  • 布局计算(layout)
  • 样式计算(recalculate style)

所以: 微任务多了,会导致 UI 渲染被推迟(例如疯狂递归 Promise.then 会卡页面)

这是高级候选人的加分点。

6. Node.js 的事件循环(面试进阶)

你至少要答出:

Node 有自己的事件循环,与浏览器不同,基于 libuv,有 6 个阶段,每个阶段都有自己的队列;process.nextTick 优先级最高,属于独立队列。

面试官会觉得你"懂事件循环的底层原理"。

7. 面试优化版答题结构(满分答案)

  1. JS 是单线程,需要异步 → Event Loop 负责调度
  2. 同步任务先执行
  3. 之后清空微任务(Promise)
  4. 再执行一个宏任务(setTimeout)
  5. 每次宏任务执行后都会再清空一次微任务
  6. 微任务优先于宏任务
  7. Promise.then 是微任务;setTimeout 是宏任务
  8. Node.js 和浏览器略有不同(加分)

8. 前端事件循环的"核心口诀"

把这些背下来,任何场景都不会错。

  • 口诀 1: 同步先执行,Promise 比 setTimeout 快
  • 口诀 2: 每一轮宏任务后,必须清空微任务
  • 口诀 3: 0 秒定时器 ≠ 立即执行
  • 口诀 4: Promise 的 then 是微任务,await 也是微任务
  • 口诀 5: 微任务塞太多会卡 UI

9. 练习题(面试模拟)

练习 1:简单版

javascript 复制代码
setTimeout(() => console.log(1));

Promise.resolve().then(() => console.log(2));

console.log(3);

顺序: 3、2、1

练习 2:进阶版

javascript 复制代码
console.log(1);

setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => console.log(3));
});

Promise.resolve().then(() => {
  console.log(4);
});

console.log(5);

顺序:

复制代码
1
5
4
2
3

练习 3:最经典"await"题

javascript 复制代码
async function test() {
  console.log(1);
  await console.log(2);
  console.log(3);
}
test();
console.log(4);

输出:

复制代码
1
2
4
3

await 把后面的部分拆成微任务。

相关推荐
晷龙烬几秒前
Vue的“小外挂”:玩转自定义指令!
前端·javascript·vue.js
gis分享者1 分钟前
如何在 Shell 脚本中如何使用条件判断语句?(中等)
面试·shell·脚本·语法·使用·判断·条件
小徐不会敲代码~2 分钟前
Vue3 学习 4
前端·vue.js·学习
小小前端要继续努力3 分钟前
边缘函数 (Edge Functions)
前端·edge
海市公约5 分钟前
CSS 核心知识点精讲:基础概念、样式规则与布局技巧
前端·css·盒子模型·选择器·网页布局·网页样式设计
蜗牛攻城狮6 分钟前
Vite 项目中 `node_modules/.vite/deps` 文件夹详解
前端·vite·构建工具
elangyipi1238 分钟前
使用CSS Contain 优化你的页面(重排和重绘)
前端·css
小小前端要继续努力9 分钟前
Islands Architecture(岛屿架构)
前端·edge
Liu.77413 分钟前
vue使用lodop控件打印
前端·javascript·vue.js
OpenTiny社区20 分钟前
TinySearchBox 综合搜索组件重磅更新:实现 Vue 2 和 Vue 3 双版本适配!
前端·javascript·vue.js