JavaScript事件循环:一次浏览器线程的"约会"指南

你是否曾好奇,为什么setTimeout有时候"不准时"?为什么Promise.then总能插队成功?今天,我们就来揭秘JavaScript中最核心的异步机制------事件循环(Event Loop),看看浏览器里的线程们是如何"约会"的。

一、进程与线程:浏览器里的"打工人"和"部门"

  • 进程:相当于一个完整的"公司",比如打开一个Chrome标签页就是创建了一个新公司。它包含了所有资源和员工(线程),从成立到倒闭(关闭标签)的整个生命周期。
  • 线程 :进程里的"打工人",比如负责和服务器聊天的HTTP线程、负责执行JS代码的引擎线程、负责画画的渲染线程

有意思的是,JS引擎线程渲染线程是对"冤家"------它们不能同时工作!就像公司里的两个部门抢会议室,一个用着另一个就得等着。这就是为什么JS是"单线程"的,同一时间只能干一件事。

二、异步:单线程的"时间管理大师"

JS既然是单线程,那遇到耗时任务(比如请求数据)怎么办?总不能干等着吧?于是它学会了"时间管理":

  • 先把同步代码全部执行完(这是主线任务)
  • 遇到异步代码,就把它暂时放到"任务队列"里排队
  • 等主线任务干完了,再去"任务队列"里取异步代码执行

这就像你在公司上班:先处理完手头的紧急工作(同步代码),再去看邮件(异步任务)。

三、Event Loop:异步任务的"优先级排序"

异步任务也分"高低贵贱",Event Loop就是负责给它们排优先级的"HR":

1. 微任务:办公室里的"关系户"

微任务是最优先处理的,相当于公司里的"关系户",包括:

  • Promise.then
  • process.nextTick(Node.js)
  • MutationObserver

这些任务会在同步代码执行完后立即插队执行,而且会一直执行到队列为空。

2. 宏任务:老老实实排队的"普通员工"

宏任务就得老老实实排队,包括:

  • setTimeout/setInterval
  • AJAX请求
  • I/O操作
  • UI渲染

3. 执行顺序:就像吃火锅

Event Loop的执行顺序可以类比吃火锅:

  1. 先吃主食(同步代码)
  2. 再吃小料(微任务)
  3. 然后涮肉(渲染页面)
  4. 最后煮面条(执行宏任务,开启下一轮循环)

四、代码实战:Event Loop的"狼人杀"

来看个经典例子,猜猜输出顺序:

javascript 复制代码
console.log('script start');
async function async1() {
  await async2()
  console.log('async1 end');
}
async function async2() {
  console.log('async2 end');
}
async1()
setTimeout(() => {
  console.log('setTimeout');
}, 0)
new Promise((resolve) => {
  console.log('promise');
  resolve()
}).then(() => {
  console.log('then1');
}).then(() => {
  console.log('then2');
});
console.log('script end');

正确答案

arduino 复制代码
script start
promise
script end
async2 end
async1 end
then1
then2
setTimeout

是不是很神奇?这里的关键是:await会先执行右边的代码,然后把后续代码扔入微任务队列。

五、await:异步世界的"插队小能手"

async/await是Promise的语法糖,但它有个特殊能力:

  1. 会把后续代码挤入微任务队列
  2. 浏览器会"提前"执行await后面的代码(相当于同步)

就像你在排队买奶茶,突然有个人拿着await的VIP卡,先点单(执行右边代码),然后去旁边等着(后续代码入微任务),等前面的人都买完了,他再回来取奶茶。

总结:Event Loop的"潜规则"

  1. 同步代码先执行(宏任务的一部分)
  2. 微任务队列清空后才会执行宏任务
  3. 每个宏任务执行完后,会检查微任务队列
  4. await后面的代码是微任务

理解了Event Loop,你就能解释为什么有些代码的执行顺序总是超出预期,也能写出更高效的异步代码。下次面试遇到这类问题,记得用"公司部门"

相关推荐
哟哟耶耶1 小时前
Starting again-02
开发语言·前端·javascript
Kitasan Burakku2 小时前
Typescript return type
前端·javascript·typescript
力Mer3 小时前
console.log()控制台异步打印与对象展开后不一致问题
前端·javascript
GISer_Jing3 小时前
得物前端二面潜在问题详解
前端·javascript·面试
未来之窗软件服务6 小时前
从东方仙盟筑基期看 JavaScript 动态生成图片技术-东方仙盟
开发语言·javascript·仙盟创梦ide·东方仙盟·图片技术
不叫猫先生6 小时前
中秋连连看小游戏开发完整教程
javascript·css·小游戏·连连看
itslife7 小时前
vite 源码 - 创建服务
前端·javascript
我的写法有点潮9 小时前
彻底理解 JavaScript 的深浅拷贝
前端·javascript·vue.js
Never_Satisfied11 小时前
在JavaScript / HTML中,转移字符导致js生成的html出错
开发语言·javascript·html
知识分享小能手11 小时前
微信小程序入门学习教程,从入门到精通,WXS语法详解(10)
前端·javascript·学习·微信小程序·小程序·vue·团队开发