【JS】javascript事件循环机制:你以为的异步王者,其实是面试刺客

JavaDog程序狗
JavaDog程序狗
发布于 2025-04-14 / 24 阅读
0
0

【JS】javascript事件循环机制:你以为的异步王者,其实是面试刺客

前言

🍊 你想听的故事

0元购的秒杀bug是怎么炼成的?

场景还原

某电商大促活动,程序员小明用setTimeout(fn,0)实现倒计时抢购。结果用户疯狂点击抢购按钮,页面直接卡死。

真相:小明不知道setTimeout的延迟参数只是最低等待时间,回调会被塞进宏任务队列排队执行,而同步代码阻塞导致回调延迟执行,最终引发雪崩效应。

🐣闪亮主角

javascript事件循环机制

大家好,我是JavaDog程序狗。今天给大家分享:

事件循环机制是 JavaScript 异步编程的核心,通过调用栈、任务队列和事件循环的协同工作,实现了异步任务的处理。理解事件循环机制对于编写高效、无阻塞的 JavaScript 代码至关重要,同时也是面试中常见的考点

你能理清这段代码的执行顺序吗?

快来自己跑一下代码,挑战一下自己的软肋吧

console.log('start');  
const interval = setInterval(() => {  
  console.log('interval');  
  Promise.resolve().then(() => console.log('interval microtask'));  
}, 0);  
setTimeout(() => {  
  console.log('timeout');  
  clearInterval(interval);  
}, 100);  
Promise.resolve().then(() => console.log('promise1'));  

🍉事故现场

一场价值10K的翻车对话

面试官:说说JS事件循环机制?

候选人(自信满满):简单!就是先执行同步代码,再处理异步任务呗~

面试官(微笑):那这段代码输出顺序是啥?

console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');

候选人(冷汗直冒):1、4、2、3?

面试官(死亡凝视):回去等通知吧…

真相:正确答案是 1 → 4 → 3 → 2

👉 狗哥锐评不懂事件循环的程序员,就像外卖小哥不看导航——迟早送错单!

正文

🚀 1.JS事件循环的本质:食堂大妈打菜模型

1. 单线程的宿命

JS天生是单线程(参考),就像食堂只有一个打菜窗口。如果大妈(主线程)遇到耗时操作(比如等红烧肉炖熟),队伍就卡死了!

2. 核心三件套

  • 调用栈(Call Stack):大妈手里的餐盘,同步代码直接装盘
  • 任务队列(Task Queue):排队的学生们,异步任务按类型分窗口(宏任务/微任务)
  • 事件循环(Event Loop):大妈的打菜循环:
  1. 清空当前餐盘(同步代码)
  2. 优先给学生发甜点(执行所有微任务)
  3. 再给下一个主食窗口发饭(执行一个宏任务)
  4. 重复以上步骤

🔥 2.血泪三连击:80%程序员踩过的坑

1. 微任务插队惨案

setTimeout(() => console.log('宏任务')); 
Promise.resolve().then(() => console.log('微任务'));
// 输出:微任务 → 宏任务

狗哥锐评微任务就像VIP会员,永远比宏任务优先!

2. setTimeout(0) 的谎言

你以为setTimeout(fn, 0)会立即执行?Naive!实际至少要等4ms(浏览器规范),比如:

console.log('开始');
setTimeout(() => console.log('超时'), 0);
console.log('结束');
// 输出:开始 → 结束 → 超时

3. Node.js vs 浏览器

场景 浏览器 Node.js
微任务优先级 Promise > MutationObserver process.nextTick > Promise
宏任务阶段 无明确阶段 分timers/poll/check等6个阶段

🥒3.防暴毙指南:事件循环的正确姿势

1. 宏任务 vs 微任务速记

类型 举例
宏任务(主食) setTimeout、setInterval、I/O操作
微任务(甜点) Promise.then、process.nextTick

2. 面试题降维打击

例题:以下代码输出顺序是?

console.log('1');
setTimeout(() => {
  console.log('2');
  Promise.resolve().then(() => console.log('3'));
}, 0);
Promise.resolve().then(() => {
  console.log('4');
  setTimeout(() => console.log('5'), 0);
});
console.log('6');

解析

  1. 同步代码:1 → 6
  2. 微任务队列:4(执行时新增宏任务5)
  3. 宏任务队列:2(执行时新增微任务3)
  4. 下一轮微任务:3
  5. 最后宏任务:5

👉 答案:1 → 6 → 4 → 2 → 3 → 5


🌟 4.终极总结:四句真言保平安

*事件循环就像渣男——永远先处理新欢(微任务),再回头找旧爱(宏任务)

  1. 同步优先清空栈
  2. 微任务比宏任务快
  3. Node阶段记分明
  4. 嵌套调用看队列

结尾

🍈猜你想问

如何与狗哥联系进行探讨

1. 关注公众号【JavaDog程序狗】

公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过360+个小伙伴啦!!!

2.踩踩狗哥博客

javadog.net

里面有狗哥的私密联系方式呦 😘

大家可以在里面留言,随意发挥,有问必答

🍯猜你喜欢

文章推荐

【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)

【规范】看看人家Git提交描述,那叫一个规矩

【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!


评论