当前位置: 首页 > news >正文

一文带你彻底弄懂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 地球是一个近似于椭球体的三维物体,而地球上的各种测量和计算都需要一个基准面来进行。基准面是一个虚拟的平面,用于测量和计算地球上的各种物理量。在地球科学中,基准面通常是一个参考椭球体&#xff0…...

【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)&#xff0…...

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 。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xf…...

万字解析设计模式之工厂方法模式与简单工厂模式

一、概述 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 切记 题目描述 题目网址&#xff1a;计算 (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 权限管理(二)

文件类型和访问权限&#xff08;事物属性&#xff09; linux前都会有一串这个字符&#xff0c;第二字符到第九字符分别表示拥有者&#xff0c;所属组&#xff0c;和other所对应的权限。那么第一个字符表示什么呢&#xff1f; 第一个字符表示文件类型&#xff1a; d&#xff1a…...

线性代数 第一章 行列式

一、概念 不同行不同列元素乘积的代数和&#xff08;共n!项&#xff09; 二、性质 经转置行列式的值不变&#xff0c;即&#xff1b; 某行有公因数k&#xff0c;可把k提到行列式外。特别地&#xff0c;某行元素全为0&#xff0c;则行列式的值为0&#xff1b; 两行互换行列式…...

查询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…...

电路的电线的拼接

不积跬步无以至千里&#xff0c;今天小编也是复习今天学习的内容&#xff0c;废话不多说&#xff0c;看博客吧&#xff01;&#xff01;&#xff01; 目录 准备条件 操作 成品 准备条件 操作 将定制的套管插入导线当中&#xff0c;24V或者0V是尖端的端子&#xff0c;后面根…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

CTF show 数学不及格

拿到题目先查一下壳&#xff0c;看一下信息 发现是一个ELF文件&#xff0c;64位的 ​ 用IDA Pro 64 打开这个文件 ​ 然后点击F5进行伪代码转换 可以看到有五个if判断&#xff0c;第一个argc ! 5这个判断并没有起太大作用&#xff0c;主要是下面四个if判断 ​ 根据题目…...

嵌入式面试常问问题

以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...