JS执行原理大揭秘:事件循环Event Loop与宏任务、微任务

前言

 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步!

 🍅 个人主页:南木元元


目录

事件循环概述

异步和单线程

同步任务

异步任务

任务队列

宏任务

微任务

例题

示例1

示例2 

示例3 

示例4 

结语


事件循环概述

JavaScript是一种单线程语言,事件循环(Event Loop)作为JavaScript的核心执行机制,可以有效地进行异步处理,保证用户界面的响应性和流畅性。

事件循环的工作流程如下:

  1. 所有同步任务都在主线程上执行,形成一个执行栈
  2. 在执行同步任务的时候,如果遇到了异步事件,会将该任务挂起,继续执行同步任务,当异步事件执行完后(如定时器到时,ajax请求返回),再将对应的回调加入到一个任务队列中等待执行,任务队列分为宏任务队列和微任务队列
  3. 当执行栈中的同步任务执行完毕后,会执行所有微任务,清空微任务队列
  4. 当执行完所有微任务后,再去执行宏任务队列中的下一个宏任务,不断循环,直到所有任务都完成。

异步和单线程

JavaScript 最初被设计为一门单线程语言,是因为它的主要用途是与用户的交互以及操作DOM。为了避免同一时间对同一个DOM元素进行操作从而导致不可预知的问题,JavaScript从一诞生就是单线程,避免了多线程环境中的复杂同步问题。

单线程的意思是在任何给定时间内,只能执行一个任务。这也意味着 JavaScript 代码执行可能面临阻塞问题,即一个耗时操作(如大量计算或高延迟的 I/O 操作)会阻塞整个程序的运行,如果代码阻塞只能一直等下去,这样导致很差的用户体验。所以事件循环的出现让 js 拥有异步的能力。

同步任务

同步任务指的是在主线程上直接执行的任务,按照代码顺序依次执行,其执行会阻塞后续代码的运行,直到任务完成。

console.log('开始执行');// 同步任务
function doSomething() {console.log('这是一个同步任务');
}doSomething();  // 调用同步函数console.log('结束执行');
//开始执行
//这是一个同步任务
//结束执行

在这个示例中, doSomething()函数的调用是同步的,因此它会立即执行,并且后续代码必须等待它执行完成才能继续。

异步任务

异步任务是在主线程执行的同时,通过回调函数等机制委托给其他线程或事件来处理的任务,它不会立即执行,而是在将来的某个时刻完成。在执行异步任务时,主线程不会等待任务完成,而是继续执行后续代码。

异步执行的机制使得 JavaScript 能够更好地处理耗时操作,保持页面的响应性。

console.log('开始执行');// 异步任务
setTimeout(() => {console.log('这是一个异步任务');
}, 1000);  // 延迟1秒后执行console.log('结束执行');
//开始执行
//结束执行
//这是一个异步任务

在上述例子中,setTimeout是一个异步任务,它会在1秒后将回调函数推入任务队列,而主线程不会等待这个1秒,而是继续执行后面的console.log('结束执行')。当主线程的同步任务执行完成后,它会检查任务队列,将异步任务的回调函数推入执行栈进行执行。

任务队列

任务队列分为宏任务队列和微任务队列两种。每当一个宏任务执行完毕,会检查微任务队列,执行所有的微任务,再继续下一个宏任务。

宏任务

宏任务是一些较大粒度的任务,包括:

  • script
  • setTimeout、setInterval
  • I/O操作,如文件读写

  • 用户交互事件,如点击事件

  • UI render(页面渲染)

  • requestAnimationFrame(在浏览器中)

  • ...

微任务

微任务通常是需要快速执行的小任务,它们的执行时机是在当前宏任务执行完毕并且在下一个宏任务开始之前。微任务的执行会比任何其他宏任务以及渲染操作更优先。包括:

  • Promise.then
  • async/await
  • process.nextTick(node中)
  • ...

为什么要引入微任务?

为了解决异步回调的问题,如果将异步回调也进行宏任务的入队操作,那么必须等前面所有的宏任务完成之后再执行回调,如果任务队列非常长,那么回调迟迟得不到执行,就会造成页面卡顿。通过引入微任务的方式,在每一个宏任务中定义一个微任务队列,当该宏任务执行完成,会先去执行其中所有微任务,执行完成才去执行下一个宏任务。

概况一下:为了给高优先级任务一个插队的机会,否则新入队的任务永远被放在队尾,微任务比宏任务有更高优先级。

例题

如果看到这里,还觉得有点懵,那么接下来就通过几个例子来帮助你更好地理解。

示例1

  1. 创建Promise实例是同步的,所以先执行主线程上的同步任务,打印1、3、4、5、7。
  2. 主线程的同步任务执行完毕后,会先执行微任务,执行Promise的then方法里的代码,打印6
  3. 微任务执行完毕后,最后执行定时器里的宏任务,打印2

示例2 

注意点:如果在执行微任务的过程中,产生新的微任务也需要一起清空;微任务队列没清空之前,是不会执行下一个宏任务的。

示例3 

注意点:事件循环每一次只执行一个宏任务

示例4 

注意点:微任务是DOM渲染前触发,宏任务是DOM渲染后触发

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~ 

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

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

相关文章

智慧手术室手麻系统源码,C#手术麻醉临床信息系统源码,符合三级甲等医院评审要求

手麻系统全套源码,C#手术麻醉系统源码,支持二次开发,授权后可商用。 手术麻醉临床信息系统功能符合三级甲等医院评审要求,实现与医院现有信息系统如HIS、LIS、PACS、EMR等系统全面对接,全面覆盖从患者入院,…

精准读取CSV/Excel数据 - 灵活指定行列范围的 Python 解决方案

文章目录 源代码项目简介导入相关库__file_exists 装饰器函数的签名和注释主要功能的实现运行演示读取 Excel 文件 源代码 https://github.com/ma0513207162/PyPrecip。pyprecip\reading\read_api.py 路径下。 项目简介 PyPrecip 是一个专注于气候数据处理的 Python 库&#xf…

9.为什么有时候会“烫烫烫”——之函数栈桢

目录 1. 什么是函数栈帧 2. 理解函数栈帧能解决什么问题呢? 3. 函数栈帧的创建和销毁解析 3.1 什么是栈? 3.2 认识相关寄存器和汇编指令 3.3 解析函数栈帧的创建和销毁 小知识:烫烫烫~ Q&A 1. 什么是函数栈帧 我们在写C语言代码…

大模型面试常考知识点1

文章目录 1. 写出Multi-Head Attention2. Pre-Norm vs Post-Norm3. Layer NormRMS NormBatch Norm 4. SwiGLU从ReLU到SwishSwiGLU 5. AdamW6. 位置编码Transformer位置编码RoPEALibi 7. LoRA初始化 参考文献 1. 写出Multi-Head Attention import torch import torch.nn as nn …

毕业设计参考-PyQt5-YOLOv8-鱼头鱼尾鱼长测量程序,OpenCV、Modbus通信、YOLO目标检测综合应用

“PyQt5-YOLOv8-鱼头鱼尾鱼长测量程序”是一个特定的软件程序,用于通过图像处理和目标检测技术来测量鱼类的长度。 视频效果: 【毕业设计】基于yolo算法与传统机器视觉的鱼头鱼尾识别_哔哩哔哩_bilibili 这个程序结合了多种技术: 1. OpenCV…

链表第7/9题--链表相交--双指针

leetcode160: 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意&#xf…

记录如何查询域名txt解析是否生效

要查询域名的TXT记录,可以使用nslookup命令。具体步骤如下:12 打开命令行终端。输入命令 nslookup -qttxt 域名,将"域名"替换为你要查询的实际域名。执行命令后,nslookup会返回域名的TXT记录值。 如何查询域名txt解析是…

厂家自定义 Android Ant编译流程源码分析

0、Ant安装 Windows下安装Ant: ant 官网可下载 http://ant.apache.org ant 环境配置: 解压ant的包到本地目录。 在环境变量中设置ANT_HOME,值为你的安装目录。 把ANT_HOME/bin加到你系统环境的path。 Ubuntu下安装Ant: sudo apt…

基于 Linux 自建怀旧游戏之 - 80 款 H5 精品小游戏合集

1)简介 最近又找到了一款宝藏游戏资源分享给大家,包含 80 款 H5 精品小游戏,都是非常有趣味耐玩的游戏,比如 植物大战僵尸、捕鱼达人、贪吃蛇、俄罗斯方块、斗地主、坦克大战、双人五子棋、中国象棋 等等超级好玩的 H5 小游戏&…

添加对象方法

添加对象方法的方法如下,这是一个通用模式 注意灵活运用。

Python深度学习基于Tensorflow(4)Tensorflow 数据处理和数据可视化

文章目录 构建Tensorflow.data数据集TFRecord数据底层生成TFRecord文件数据读取TFRecord文件数据图像增强 数据可视化 构建Tensorflow.data数据集 tf.data.Dataset表示一串元素(element),其中每个元素包含一个或多个Tensor对象。例如&#xf…

如何在IDEA中找到jar包路径对应的maven依赖

1.找到文件所对应的jar包路径 2.按照箭头顺序操作 3.查找文件所对应的依赖

商场综合体能源监管平台,实现能源高效管理

商场作为大型综合体建筑,其能源消耗一直是备受关注的问题。为了有效管理商场能耗,提高商场能源效率,商场综合体能源监管平台应运而生。 商场综合体能源监管平台可通过软硬件一起进行节能监管,硬件设备包括各种传感器、监测仪表和…

FastReID使用教程、踩坑记录

近期在尝试使用FastReID,期间对FastReID架构、损失函数、数据集准备、模型训练/评估/可视化/特征向量输出、调试debug记录等进行记录。 FastReID架构理解 关于FastReID的介绍,可点击此链接前往查询。 ReID和FastReID架构 对于模型架构、损失函数、实验…

进程间通信 管道

前言 ubuntu系统的默认用户名不为root的解决方案(但是不建议):轻量应用服务器 常见问题-文档中心-腾讯云 (tencent.com) 进程间通信的基本概念 进程间通信目的:进程间也是需要协同的,比如数据传输、资源共享、通知事件…

PG的事务ID回卷逻辑

PG到目前为止使用的事务ID仍然是32位的,在内存计算时虽然已经使用64位事务ID,但是存储在页中tuple仍然使用32位事务ID,这就是说,事务ID回卷仍然是必须处理的问题。 所谓PG事务ID回卷,简单地说,就是在数据库…

基于FPGA实现的HDMI TO MIPI扩展显示器方案

FPGA方案,HDMI IN接收原始HDMI 信号,输出显示到LCD 屏上 客户应用:扩展显示器 主要特性: 1.支持2K以下任意分辨率显示 2.支持OSD 叠加多个图层 3.支持MIPI/EDP/LVDS/RGB屏 4.支持放大缩小匹配屏分辨率 5.零延时,输…

【vue-echarts】 报错问题解决 “Error: Component series.pie not exists. Load it first.“

目录 问题描述解决【解决1】【解决2】 问题描述 使用 vue-echarts 时导入的文件 import VChart from vue-echarts/components/ECharts import echarts/lib/chart/line import echarts/lib/chart/bar import echarts/lib/chart/pie import echarts/lib/component/legend impor…

文心一言 VS 讯飞星火 VS chatgpt (255)-- 算法导论18.3 1题

一、请说明依次从图18-8(f)中删除C、P和V后的结果。如果要写代码,请用go语言。 文心一言: 首先,让我们明确一点:由于您没有提供具体的图18-8(f)的内容,我只能假设它是一个数据结构(可能是图、树或列表等&…

Wireshark下载安装和使用教程

Wireshark下载安装和使用教程 Wireshark(前身 Ethereal)是一个网络包分析工具。该工具主要是用来捕获网络数据包,并自动解析数据包,为用户显示数据包的详细信息,供用户对数据包进行分析。 它可以运行在 Windows 和 L…