一文带你彻底弄懂js事件循环(Event Loop)
JavaScript事件循环是JavaScript运行时环境中处理异步操作的机制。它允许JavaScript在执行同步代码的同时处理异步任务,以避免阻塞线程并提供更好的用户体验。
本文将在浏览器异步执行原理基础上带你彻底弄懂js的事件循环机制。
浏览器JS异步执行原理
js是单线程的,也就是说同一时刻只能做一件事情。
作为一个浏览器脚本语言,这与javascript的用途有关。
JavaScript主要用于与用户进行交互和操作文档对象模型(DOM)。在网页中,用户的操作和页面的渲染是非常重要的,如果JavaScript是多线程的,可能会导致多个线程同时修改DOM,造成不可预测的结果。
因此,为了保证页面的安全性和稳定性,JavaScript被设计为单线程的。它使用事件循环机制来处理异步任务,确保任务的按序执行,避免了多线程带来的竞态条件和死锁等问题。
虽然JavaScript是单线程的,但是通过异步编程模型,可以实现非阻塞的操作。例如,通过使用回调函数、Promise、async/await等方式,可以在执行异步任务时,不会阻塞后续的代码执行,从而提高了程序的响应性能。
需要注意的是,虽然JavaScript本身是单线程的,但是浏览器是多线程的。浏览器中除了JavaScript引擎线程外,还有渲染线程、网络线程、定时器线程等。这些线程可以并行执行,提高了浏览器的性能和用户体验。但是JavaScript代码本身在执行时仍然是单线程的。

执行栈与任务队列
1. 执行栈(Call Stack):
执行栈是一种数据结构,用于管理函数的执行上下文(execution context)。当函数被调用时,会创建一个对应的执行上下文,并将其推入执行栈的顶部。执行栈遵循先进后出(LIFO)的原则,即最后进入的执行上下文最先执行,执行完毕后会从栈顶弹出。
当JavaScript引擎执行代码时,会将函数调用和表达式求值的过程以栈的形式进行管理。每当遇到函数调用时,会将该函数的执行上下文推入执行栈,然后执行函数体中的代码。如果函数内部又调用了其他函数,会将新的执行上下文推入执行栈,形成嵌套的执行上下文。
当函数执行完毕或遇到return语句时,会将该执行上下文从执行栈中弹出,继续执行之前的上下文。当执行栈为空时,表示所有的函数都已执行完毕,程序结束。
2. 任务队列(Task Queue):
任务队列是一种用于存储待执行的任务的队列。在JavaScript中,任务队列主要用于存储异步任务的回调函数。
当遇到异步任务(如定时器、网络请求、事件监听等)时,会将相应的回调函数放入任务队列中,而不会立即执行。当执行栈为空时,JavaScript引擎会从任务队列中取出一个任务,将其对应的回调函数推入执行栈,开始执行。
任务队列采用先进先出(FIFO)的原则,即先进入队列的任务会先被执行。这保证了异步任务按照其被触发的顺序执行,避免了回调函数的竞争和混乱。
通过执行栈和任务队列的协作,JavaScript实现了异步编程模型,使得程序能够在等待异步任务完成的同时继续执行其他任务,提高了程序的并发性和响应性能。
我们看下面一个列子更深入的理解一下执行栈和任务队列这个概念:
console.log('1')setTimeout(() => {console.log('2')},0)console.log('3')//1 3 2

由上图可以清晰的看出,同步代码直接放入执行栈中立即执行,而异步代码则被放入了宿主环境中,而宿主环境中的代码会等待正确的时机,时机一到宿主环境会把里面的回调函数推送给任务队列,执行栈执行完之后会看任务队列里面有没有异步任务,有则把里面的代码推送到执行栈中执行。
宏任务和微任务
任务队列中的任务分为宏任务(macro-task)和微任务(micro-task)两种类型。宏任务包括定时器任务、事件任务等,而微任务主要包括Promise的回调函数、MutationObserver的回调函数等。微任务的执行优先级高于宏任务,即在执行栈为空时,会先执行所有的微任务,然后再执行宏任务。
1. 宏任务(macro-task)(宿主环境-浏览器、node):
宏任务是一类较为重量级的任务,包括但不限于以下几种:
- 定时器任务(setTimeout、setInterval等)
- I/O任务(文件读写、网络请求等)
- UI渲染任务(页面重绘、动画渲染等)
- 事件任务(鼠标点击、键盘事件等)
宏任务会被推入任务队列中,在执行栈为空时,JavaScript引擎会从任务队列中取出一个宏任务,将其对应的回调函数推入执行栈,开始执行。宏任务之间的执行顺序是按照它们被添加到任务队列的顺序来执行的。
2. 微任务(micro-task)(js引擎):
微任务是一类较为轻量级的任务,主要包括以下几种:
- Promise的回调函数(then、catch、finally)
- MutationObserver的回调函数
- process.nextTick(Node.js环境)
微任务会在当前宏任务执行完毕后立即执行,而不需要等待其他宏任务。当执行栈为空时,JavaScript引擎会先执行所有的微任务,然后再执行下一个宏任务。微任务之间的执行顺序是按照它们被添加到任务队列的顺序来执行的。
接着上面的列子再来分析一下:
console.log('1')setTimeout(() => {console.log('2')},0)new Promise(function (resolve) {console.log('promise1')resolve()console.log('promise2')}).then(function () {console.log('promise3')})console.log('3')//1 promise1 promise2 3 promise3 2

上图可清晰的看出,首先执行执行栈中的任务,依次打印1-promise1-promise2-3,然后把微任务中的任务放到执行栈中,打印promise3,微任务队列执行完之后,再把宏任务中的队列放到执行栈中执行,打印2
总结
javaScript事件循环是一种用于管理和调度异步代码执行的机制。它的核心思想是通过执行栈、任务队列和事件触发来实现异步编程。
事件循环的执行过程可以总结如下:
1. 执行全局同步代码:
首先,JavaScript引擎会执行全局上下文中的同步代码,将函数调用和表达式求值的过程以栈的形式进行管理,即执行栈(Call Stack)。
2. 处理微任务:
在执行全局同步代码的过程中,如果遇到微任务(Promise的回调函数、MutationObserver的回调函数等),会将其推入微任务队列。
3. 处理宏任务:
当执行栈为空时,JavaScript引擎会从任务队列中取出一个宏任务,将其对应的回调函数推入执行栈,开始执行。宏任务包括定时器任务(setTimeout、setInterval等)、I/O任务(文件读写、网络请求等)、UI渲染任务(页面重绘、动画渲染等)和事件任务(鼠标点击、键盘事件等)。
4. 处理微任务:
在执行完一个宏任务后,会检查微任务队列是否为空,如果不为空,则依次执行所有的微任务。微任务的执行优先级高于宏任务,即在同一个宏任务中,会先执行所有的微任务,然后再执行下一个宏任务。
5. 重复执行步骤3和步骤4:
事件循环会不断重复执行步骤3和步骤4,直到执行栈和任务队列都为空。
需要注意的是,事件循环是单线程的,即一次只能执行一个任务。当一个任务正在执行时,其他任务需要等待。这也是为什么长时间运行的任务会阻塞UI渲染和其他任务的原因。
合理地使用异步编程和事件循环机制可以提高程序的性能和响应性能,避免了阻塞和卡顿。同时,需要注意避免过多的嵌套回调和过度依赖异步操作,以免造成代码可读性和维护性的问题。
相关文章:
一文带你彻底弄懂js事件循环(Event Loop)
JavaScript事件循环是JavaScript运行时环境中处理异步操作的机制。它允许JavaScript在执行同步代码的同时处理异步任务,以避免阻塞线程并提供更好的用户体验。 本文将在浏览器异步执行原理基础上带你彻底弄懂js的事件循环机制。 浏览器JS异步执行原理 js是单线程…...
数据结构与算法:二叉树之“堆排序”
目录 一、树概念及结构 二、二叉树树概念及结构 特殊的二叉树 三、堆的概念及结构 四、堆的创建 1、声明结构体 2、初始化 3、销毁 4、添加新元素 5、交换元素 6、向上调整 7、判断堆是否为空 8、移除堆顶元素 9、向下调整 10、获取堆元素个数 五、使用堆排序…...
gma 2 教程(三)坐标参考系统:2.基准面/椭球体
安装 gma:pip install gma 地球是一个近似于椭球体的三维物体,而地球上的各种测量和计算都需要一个基准面来进行。基准面是一个虚拟的平面,用于测量和计算地球上的各种物理量。在地球科学中,基准面通常是一个参考椭球体࿰…...
【1day】复现广联达-Linkworks 协同办公管理平台信息泄露漏洞
注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现...
Spring Cloud之ElasticSearch的学习【详细】
目录 ElasticSearch 正向索引与倒排索引 数据库与elasticsearch概念对比 安装ES、Kibana与分词器 分词器作用 自定义字典 拓展词库 禁用词库 索引库操作 Mapping属性 创建索引库 查询索引库 删除索引库 修改索引库 文档操作 新增文档 查找文档 修改文档 全量…...
vscode免密码认证ssh连接virtual box虚拟机
文章目录 安装软件virtual box配置vscode配置创建并传递密钥连接虚拟机最后 安装软件 安装vscode和virtual box,直接官网下载对应软件包,下载之后,点击执行,最后傻瓜式下一步安装即可 virtual box配置 创建一个仅主机网络的网卡 …...
【Linux】Centos yum源替换
YUM是基于RPM包管理,能够从指定的服务器自动下载RPM包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。 CentOS 8操作系统版本结束了生命周期(EOL)࿰…...
uniapp组件初始化的销毁(监听隐藏事件)
onHide是监听隐藏事件onHide() {console.log("销毁");this.clearTimer(); }, onShow(){console.log("初始化");this.getOrderInfo() },...
leetcode:1207. 独一无二的出现次数(python3解法)
难度:简单 给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。 如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。 示例 1: 输入:arr [1,2,2,1,1,3] 输出:true 解释&…...
2023秋《论文写作》课程总结
2023秋《论文写作》课程总结 授课教师为闵帆教授,原文链接《论文写作》 文章目录 2023秋《论文写作》课程总结一、关于写作工具二、关于写作中的单词、短语、语法等三、关于论文题目四、关于摘要和关键词五、关于引言部分六、关于方法及实验部分七、关于结论八、关…...
Linux学习第27天:Platform设备驱动开发: 专注与分散
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 专注与分散是我在题目中着重说明的一个内容。这是今天我们要学习分离与分层概念的延伸。专注是说我们要专注某层驱动的开发,而对于其他层则是芯片厂商…...
最长公共子序列
题目描述 给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符…...
万字解析设计模式之工厂方法模式与简单工厂模式
一、概述 1.1简介 在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的…...
One-to-N N-to-One: Two Advanced Backdoor Attacks Against Deep Learning Models
One-to-N & N-to-One: Two Advanced Backdoor Attacks Against Deep Learning Models----《一对N和N对一:针对深度学习模型的两种高级后门攻击》 1对N: 通过控制同一后门的不同强度触发多个后门 N对1: 只有当所有N个后门都满足时才会触发…...
洛谷 B2009 计算 (a+b)/c 的值 C++代码
目录 题目描述 AC Code 切记 题目描述 题目网址:计算 (ab)/c 的值 - 洛谷 AC Code #include<bits/stdc.h> using namespace std; int main() {int a,b,c;cin>>a>>b>>c;cout<<(ab)/c<<endl;return 0; } 切记 不要复制题…...
Arduino驱动ME007-ULA防水测距模组(超声波传感器)
目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 3.1、读取串口数据...
Linux 权限管理(二)
文件类型和访问权限(事物属性) linux前都会有一串这个字符,第二字符到第九字符分别表示拥有者,所属组,和other所对应的权限。那么第一个字符表示什么呢? 第一个字符表示文件类型: d:…...
线性代数 第一章 行列式
一、概念 不同行不同列元素乘积的代数和(共n!项) 二、性质 经转置行列式的值不变,即; 某行有公因数k,可把k提到行列式外。特别地,某行元素全为0,则行列式的值为0; 两行互换行列式…...
查询Oracle所有用户相关信息
$sqlplus / as sysdba 1. 查询oracle中所有用户信息 select * from dba_users; select * from all_users; select distinct owner from all_objects; 2. 只查询用户和密码 select username,password from dba_users; 3. 查询当前用户信息 select * from dba_ustats; 4…...
电路的电线的拼接
不积跬步无以至千里,今天小编也是复习今天学习的内容,废话不多说,看博客吧!!! 目录 准备条件 操作 成品 准备条件 操作 将定制的套管插入导线当中,24V或者0V是尖端的端子,后面根…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...
StarRocks 全面向量化执行引擎深度解析
StarRocks 全面向量化执行引擎深度解析 StarRocks 的向量化执行引擎是其高性能的核心设计,相比传统行式处理引擎(如MySQL),性能可提升 5-10倍。以下是分层拆解: 1. 向量化 vs 传统行式处理 维度行式处理向量化处理数…...
