尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

事件循环其实很简单!

事件循环其实很简单!
📅 发布时间:2026/6/19 7:04:35

一、概念

JavaScript 是单线程执行(基于执行栈 / 调用栈 call stack),事件循环负责不断地从各种任务队列里取任务执行——以保证异步任务的函数回调按规则有序运行,浏览器环境和 Node.js 环境都使用事件循环,尽管他们的事件循环逻辑并不相同。

之所以函数的执行基于“栈”这种结构,是因为 js 函数允许嵌套,先调用的函数需要等待内部函数的调用执行完毕才能执行,也就是先调用后执行的逻辑,正好满足“栈”这种数据结构。

执行栈/调用栈是针对函数调用来说的,而我们 js 任务的执行依赖于任务队列,先进入队列的任务会先执行,而且一个任务中可能存在多个函数。要注意一个是函数调用的机制,一个是任务执行的机制,不是一回事!

二、基本构件

  • ​Call Stack(调用栈)​:同步代码入栈执行、执行完出栈。
  • ​宏任务(macrotask / task)队列​:例如 setTimeout、setInterval、setImmediate(Node)、DOM 事件、I/O 回调、UI 渲染触发等。

    宏任务作为之前的一种笼统叫法,现代浏览器对这些任务做了更细的划分,对他们都统称为了 task,不同的任务具有不同的队列。不过,微任务的概念一直被保留使用。

  • ​微任务(microtask / job)队列​:例如 Promise.then/catch/finally、async+await、queueMicrotask、MutationObserver(浏览器)、process.nextTick(Node)。
  • ​渲染/绘制阶段(browser)​:在合适时机把更新绘制到屏幕(通常在 macrotask 完成并且 microtasks 已清空之后)。

    主要为了后面对于任务执行和浏览器渲染顺序的理解。

  • ​事件循环(event loop)​:不断循环——执行一个 macrotask → 清空所有 microtasks → 执行渲染(若需要) → 下一个 macrotask。

三、浏览器里的执行模型

循环的每一轮(tick)大致顺序:

  1. 从 macrotask queue 取出一个任务并执行(例如页面初始 script)。
  2. 当前任务执行完后,立即运行并清空 ​microtask queue​(每出现一个 microtask,它会被加入队列;直到队列空才返回)。

    microtasks 在同一轮里可能不断产生并被立即处理。

  3. 当 microtasks 清空后,会进行一次 ​渲染/绘制​(如果需要)。
  4. 进入下一轮 macrotask。

结论:​microtask 的优先级高于下一个 macrotask​。

这里多提一嘴“tick”,不知道有多少同学看到这个“tick”,马上就会联想到 Vue 中的 nextTick,其实,他们确实有一定渊源。

事件循环中的 tick :

tick = 一次事件循环的执行周期 = Task → Microtask → Render → 下一 tick

而 Vue.nextTick 作用试讲 DOM 更新后的回调放入微任务队列(或者退化为宏任务),主要是为了解决 DOM 的异步更新导致无法得到最新 DOM。Vue 源码逻辑:

if (Promise) microtask
else if (MutationObserver) microtask // 旧浏览器
else macrotask fallback // setImmediate(IE专属) -> setTimeout(Macrotask,最差)

Vue 官方文档对于 nextTick 的解释是:等待下一次 DOM 更新刷新的工具方法。和事件循环中的 tick 何其相似。

除此之外,对于浏览器渲染和事件循环结合很多同学没有了解过,以下是一个结合浏览器渲染的例子:

<script>
console.log('start');setTimeout(() => console.log('timeout'), 0);Promise.resolve().then(() => console.log('promise'));requestAnimationFrame(() => console.log('raf'));console.log('end');
</script>

在浏览器输出:start end promise raf timeout

解释:

  • 同步:start、end
  • microtask: promise
  • 渲染相关:requestAnimationFrame 在下一帧渲染前执行(在 microtasks 清空后,但通常在 macrotask 之前的 render 时机),所以 raf 在 timeout 之前
  • setTimeout 是下一轮 macrotask,所以最后输出。

四、Node.js(libuv)与浏览器的区别

Node 的底层是 libuv,事件循环分多个阶段:

  1. timers(处理 setTimeout/setInterval)
  2. pending callbacks(I/O 回调)
  3. idle, prepare(内部使用)
  4. poll(检索新的 I/O 事件并执行)
  5. check(处理 setImmediate)
  6. close callbacks(socket close 等)

微任务(Promise callbacks)是在每个阶段执行后 ​立即清空​(microtask checkpoint);另外 Node 有 process.nextTick,其优先级甚至高于 microtasks(会在当前阶段马上执行,且会在 Promise microtasks 之前运行)。

我不想放很多面试题去讲解,因为面试题是做不完的,而知识的核心重点就是这些。

上面的理论搞懂了,基本上相关面试题都可以做对。

相关新闻

  • Upgrade Your Key Programming: New Style CG A22-3+1 Flip-4BTN Wire Remote for CGDI K2 (5pcs/lot)
  • 深入解析:使用 Triton 实现 Flash Attention2 - 让大模型训练飞起来
  • 题解:P8819 [CSP-S 2022] 星战

最新新闻

  • 杭州GEO优化公司2026年6月Top5:选型疑问与避坑全解 - GEO优化
  • 2026年最新武汉光谷科技职业技术学校联系方式及招生办电话号码 - 武汉中职最新信息发布
  • 揭秘Mac鼠标滚轮终极优化:让外接鼠标拥有触控板般的丝滑体验
  • MC9RS08KA2内部时钟与定时器深度解析:从原理到低功耗设计实战
  • 2026玉林本地人必选防水补漏检测维修公司靠谱服务商TOP5推荐:房屋渗漏水检测维修/卫生间/厨房/天花板/阳台/外墙渗漏水检测补漏维修-暗管漏水检测专业仪器精准定位漏水点 - 即刻修防水
  • PingFangSC字体实战:现代Web开发中的跨平台中文字体终极配置指南

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号