JavaScript事件循环机制

JavaScript 事件循环机制(Event Loop)详解

JavaScript 是 单线程、非阻塞 语言,依赖 事件循环(Event Loop) 来实现异步编程。它的执行模型包括 调用栈(Call Stack)、任务队列(Task Queue)和微任务队列(Microtask Queue)


1. 事件循环(Event Loop)基本流程

事件循环的核心工作方式:

  1. 同步任务(Synchronous) 进入 调用栈 依次执行。
  2. 遇到 异步任务(如 setTimeout、Promise、I/O 操作),交给 Web API(如浏览器、Node.js 运行时)处理,并继续执行同步代码。
  3. 同步代码执行完毕,调用栈清空,事件循环检查 微任务队列(Microtask Queue),依次执行所有微任务。
  4. 微任务执行完毕,进入 宏任务队列(Macro Task Queue),取出第一个任务执行。
  5. 重复以上步骤。

2. 任务类型:同步任务 vs 异步任务

JavaScript 任务分为:

(1) 同步任务(Synchronous)

  • 直接执行,放入 调用栈(Call Stack)
  • 例子:
    console.log('同步任务1'); // 立即执行
    

(2) 异步任务(Asynchronous)

  • 由 Web API 处理,待合适时机进入任务队列:
    • 宏任务(Macro Task)
    • 微任务(Micro Task)

3. 宏任务(Macro Task) vs 微任务(Micro Task)

任务类型常见API进入队列
宏任务(Macro Task)setTimeoutsetIntervalsetImmediate(Node.js)、I/OUI渲染任务队列(Task Queue)
微任务(Micro Task)Promise.then()queueMicrotask()MutationObserverprocess.nextTick()(Node.js)微任务队列(Microtask Queue)

4. 事件循环执行流程

console.log('同步任务1');setTimeout(() => {console.log('宏任务1');
}, 0);Promise.resolve().then(() => {console.log('微任务1');
});console.log('同步任务2');

执行顺序解析

  1. console.log('同步任务1') 执行(同步任务)
  2. setTimeout() 放入 宏任务队列,等待执行
  3. Promise.then() 放入 微任务队列
  4. console.log('同步任务2') 执行(同步任务)
  5. 调用栈清空,检查 微任务队列,执行 console.log('微任务1')
  6. 微任务清空后,执行 宏任务队列,输出 console.log('宏任务1')
最终输出顺序
同步任务1
同步任务2
微任务1
宏任务1

5. setTimeout(fn, 0) 为什么不立即执行?

  • setTimeout(fn, 0) 也会进入 宏任务队列,需要等当前同步任务执行完毕,并在 微任务全部执行完毕后,才能执行。
  • 示例
    setTimeout(() => console.log('宏任务'), 0);
    Promise.resolve().then(() => console.log('微任务'));
    console.log('同步任务');
    
    执行顺序
    同步任务
    微任务
    宏任务
    

6. PromisesetTimeout 谁先执行?

  • Promise.then() 是微任务,会先执行
  • setTimeout() 是宏任务,等微任务执行完才执行

示例

setTimeout(() => console.log('setTimeout'), 0);
Promise.resolve().then(() => console.log('Promise'));

执行顺序

Promise
setTimeout

7. 事件循环完整示例

console.log('start');setTimeout(() => {console.log('setTimeout');
}, 0);Promise.resolve().then(() => {console.log('Promise1');
}).then(() => {console.log('Promise2');
});console.log('end');

执行顺序

  1. console.log('start')(同步任务)
  2. setTimeout() 进入 宏任务队列
  3. Promise.then() 进入 微任务队列
  4. console.log('end')(同步任务)
  5. 同步任务结束,执行微任务
    • Promise1
    • Promise2
  6. 微任务执行完毕,执行宏任务
    • setTimeout

最终输出:

start
end
Promise1
Promise2
setTimeout

8. async/await 也是微任务

示例

async function asyncFunc() {console.log('A');await Promise.resolve();console.log('B');
}console.log('C');
asyncFunc();
console.log('D');

执行顺序

C
A
D
B

解释

  1. console.log('C')(同步任务)
  2. 调用 asyncFunc(),输出 A
  3. await Promise.resolve()console.log('B') 进入 微任务队列
  4. console.log('D')(同步任务)
  5. 执行微任务
    • console.log('B')

9. setTimeout()setImmediate()(Node.js)

Node.js 中:

  • setTimeout(fn, 0) 进入 定时器队列
  • setImmediate(fn) 进入 Check 队列
  • setImmediate() 通常比 setTimeout(0) 先执行

示例

setTimeout(() => console.log('setTimeout'), 0);
setImmediate(() => console.log('setImmediate'));

输出顺序(Node.js)

setImmediate
setTimeout

10. 关键点总结

概念说明
同步任务立即执行,进入 调用栈
异步任务由 Web API 处理,稍后执行
宏任务(Macro Task)setTimeoutsetIntervalsetImmediateI/O
微任务(Micro Task)Promise.then()queueMicrotask()MutationObserver
事件循环(Event Loop)先执行同步任务 → 再执行微任务 → 再执行宏任务

11. 最佳实践

避免阻塞主线程

  • 使用 setTimeout(fn, 0)requestIdleCallback(fn) 处理密集计算

优先使用微任务优化异步流程

  • Promise.then()setTimeout() 先执行

了解 async/await 也是微任务

  • await 后的代码会在微任务队列中执行

总结

  1. JavaScript 是单线程,使用事件循环管理异步任务
  2. 任务分为
    • 同步任务(调用栈直接执行)
    • 异步任务(进入宏任务/微任务队列)
  3. 执行顺序
    • 先执行同步任务
    • 再执行所有微任务
    • 最后执行宏任务
  4. Promise.then()setTimeout() 先执行
  5. async/await 本质上是 Promise,属于微任务

这些概念对于理解 JavaScript 的异步执行至关重要!🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/72041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型架构记录4-文档切分 (chunks构建)

chunks: 块 trunks : 树干 “RAG”通常指 检索增强生成(Retrieval-Augmented Generation) 主要框架:用户提query,找到和它相关的,先把问题转换为向量,和向量数据库的数据做比较,检…

物联网IoT系列之MQTT协议基础知识

文章目录 物联网IoT系列之MQTT协议基础知识物联网IoT是什么?什么是MQTT?为什么说MQTT是适用于物联网的协议?MQTT工作原理核心组件核心机制 MQTT工作流程1. 建立连接2. 发布和订阅3. 消息确认4. 断开连接 MQTT工作流程图MQTT在物联网中的应用 …

第27周JavaSpringboot电商进阶开发 1.企业级用户验证

课程笔记:注册邮箱验证 一、概述 从本小节开始,将学习如何进行注册邮箱验证。主要任务是给项目配置一个公共邮箱(可自己注册或由公司提供),用于向用户发送验证码,帮助用户完成注册流程。课程中以QQ邮箱为…

数据库---sqlite3

数据库: 数据库文件与普通文件区别: 1.普通文件对数据管理(增删改查)效率低 2.数据库对数据管理效率高,使用方便 常用数据库: 1.关系型数据库: 将复杂的数据结构简化为二维表格形式 大型:Oracle、DB2 中型:MySql、SQLServer …

音视频软件工程师面试题

一、基础知识 编解码相关 H.264 和 H.265(HEVC)的主要区别是什么?视频编解码的基本流程是什么?关键技术有哪些?音频编解码(如 AAC、MP3、Opus)的区别和应用场景?什么是 B 帧、P 帧、I 帧?它们的作用是什么? 流媒体协议RTMP、HTTP-FLV、HLS、WebRTC 的区别和应用场景…

【系统架构设计师】测试方法

目录 1. 说明2. 静态测试3. 动态测试4. 黑盒测试5. 白盒测试6. 灰盒测试7. 自动化测试8.例题8.1 例题1 1. 说明 1.软件测试方法的分类有很多种,以测试过程中程序执行状态为依据可分为静态测试(Static Testing,ST)和动态测试&…

tomcat配置应用----server.xml文件具体配置

1.tomcat项目目录 默认项目目录:tomcat安装目录/webapps目录 如上图所示,在tomcat的项目目录下有很多子文件夹,这些子文件夹中都有一个项目首页。 如上图所示,将来我们去使用IP加端口号的方式去访问tomcat的时候,默认是…

Spring Boot 调用DeepSeek API的详细教程

目录 前置准备步骤1:创建Spring Boot项目步骤2:配置API参数步骤3:创建请求/响应DTO步骤4:实现API客户端步骤5:创建控制器步骤6:异常处理步骤7:测试验证单元测试示例Postman测试请求 常见问题排查…

多维数据聚合方案:SQL GROUPING SETS深度解析

一、什么是GROUPING SETS? GROUPING SETS是SQL标准中的多维聚合运算符,允许在单个查询中实现多维度组合的分组统计。相较于传统UNION ALL方案,性能可提升3-10倍(TPC-DS基准测试)。 二、核心语法解析 SELECT column1,…

Excel中国式排名,3种方法!

大家好,我是小鱼。 什么是中国式排名呢? 举个例子比如说公司一共有10名员工进行成绩考核,如果9个人考核成绩都是90分,你是89分,按照国际惯用的排名法则:9 个人考核成绩并列第一,你第10名&…

哪些业务场景更适合用MongoDB?何时比MySQL/PostgreSQL好用?

哪些业务场景更适合用MongoDB?何时比MySQL/PostgreSQL好用? 就像淘宝的个性化推荐需要灵活调整商品标签,MongoDB这种"变形金刚"式的数据库,在处理以下三类中国特色业务场景时更具优势: 一、动态数据就像&q…

深度解读:OpenAI发布GPT-5的技术突破与商业影响

引言 2025年2月,OpenAI正式发布GPT-5,这一被誉为“AI新纪元开篇之作”的模型,不仅实现了技术架构的颠覆性创新,更以免费开放策略引发行业地震。本文将从技术突破、商业影响、行业竞争格局及未来挑战四个维度,全面解析…

网络防火墙是什么有什么用_网络防火墙:守护信息安全的重要屏障

网络防火墙的基本概念 网络防火墙是网络安全领域的重要组成部分,它充当着内部网络和外部网络之间的安全防护层。防火墙能够监控和控制进出网络的数据流,只允许符合安全策略的信息通过,从而有效阻止潜在威胁的入侵。简而言之,网络…

C# WPF 串口通信

C# WPF 串口通信 安装依赖库 安装依赖库 System.IO.Ports using System.Diagnostics; using System.IO.Ports; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windo…

【玩转23种Java设计模式】结构型模式篇:组合模式

软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 汇总目录链接&…

如何选取合适的 NewRatio 值来优化 JVM 的垃圾回收策略

目录 一、垃圾回收模型简介 (一)新生代(Young Generation) (二)老年代(Old Generation) (三)NewRatio 的作用与影响 (四)图解&am…

Element Plus中的树组件的具体用法(持续更新!)

const defaultProps {//子树为节点对象的childrenchildren: children,//节点标签为节点对象的name属性label: name, } 属性 以下是树组件中的常用属性以及作用: data:展示的数据(数据源) show-checkbox:节点是否可…

第十一届蓝桥杯单片机国赛

什么?4T模拟赛和省赛做起来轻轻松松?不妨来挑战一下第十一届国赛,这一届的国赛居然没考超声波、串口通信!只要你正确地理解了题目的意思,规避出题人挖的坑,拿个国一轻轻松松。 附件:第十一届蓝桥…

大彩串口屏开发 —— MODBUS通信

目 录 Modbus通信方式 1 使用变量与协议设置方式 2 使用LUA脚本方式 3 两者结合 Modbus通信 大彩串口屏可以采用三种方式实现与其它设备进行modbus通信和逻辑处理。 方式 1 使用变量与协议设置 步骤1 在协议设置里进行设置,包括开启modbus协议,屏做为主…