事件循环机制(Event Loop)和宏任务(macro-tast)微任务(micro-tast),详细讲解!!!
“事件循环机制” 和 “宏任务微任务” 也是前端面试中常考的面试题了。
首先,要深刻理解这些概念的话,需要回顾一些知识点。
知识点回顾
1、进程与线程
进程。
程序运行需要有它自己的专属内存空间,可以把这块内存空间简单的理解为进程
每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。
线程。
线程是CPU的基本调度单位,是程序执行的一个完整流程。
一个进程至少有一个线程,所以在进程开启后会自动创建一个线程来运行代码,该线程称之为 主线程。
如果程序需要同时执行多块代码,主线程就会开启更多的线程来执行代码,所以一个进程中可以包含多个线程。
简单总结一些它们的关系:
一个进程中一般至少有一个运行的线程——主线程
一个进程中也可以同时运行多个线程
多个进程之间的数据是不能同时直接共享的
那浏览器有哪些进程与线程呢?
浏览器内部的工作其实极为复杂,它是多进程多线程的。且为了避免相互影响,它会自动启动多个进程。
比如,我们可以在浏览器任务管理器查看一下所有进程。

其中,最主要的进程有:
浏览器进程
主要负责界面显示、用户交互、子进程管理等。浏览器进程内部会启动多个线程处理不同的任务。
网络进程
负责加载网络资源。网络进程内部会启动多个线程来处理不同的网络任务
渲染进程
渲染进程启动后,会开启一个 渲染主线程,主线程负责执行 HTML、CSS、JS代码
默认情况下,浏览器会为每一个标签页开启一个新的渲染进程,以保证不同的标签页之间不互相影响。
2、JS是单线程还是多线程?
JS肯定是单线程的。
如果是多线程会发生什么? 如果JS是多线程,那当两个线程同时对dom进行操作,一个是添加事件,一个是删除dom,要怎么处理? 所以为了避免这种情况,JS选择只用一个主线程来执行代码以保证一致性。
3、怎么去理解JS的异步?
上面写到JS是单线程的,它运行在浏览器的渲染主线程中,且渲染主线程有且仅有一个。 但是它却有很多任务,比如渲染页面、执行JS都包含在内。
那如果不使用异步,而是同步的方式,就极有可能造成主线程的阻塞,那其他任务就无法执行了,一方面消耗时间,另一方面页面又没法及时更新,很容易有卡死现象。
所以浏览器采用异步方式。 具体做法其实就是, 比如一些任务发生了,假设现在遇到了计时器,主线程会将任务交给其他线程处理,自己立马结束这个任务,转而执行后续代码。 而等其他线程完成后,将事先传递的回调函数包装成任务,再加入到消息队列的末尾排队,等待主线程的调度执行。
在这种异步模式下,浏览器就可以避免阻塞。
这一段解释涉及到操作系统的进程调度问题和我们所要理解的事件循环机制。暂时看不懂的,可以先往下看。
4、进程调度
进程调度的知识点稍多,比如抢占式调度,非抢占式调度,先来先服务,优先级调度等等。
我们这里就简单介绍一下先来先服务(FCFS)。
它的算法思想其实就是从“公平”的角度来考虑的 (我们可以理解成 排队买东西,先来排队的优先买)。所以它的算法规则,其实是按照 作业/进程 到达的先后顺序进行服务。 它是一种非抢占式算法 (可以理解成 “不允许你插队”),它不会导致 “饥饿”现象(也就是一直轮不到执行,苦苦等待),因为只要排队终有一天会轮到它的。
事件循环机制
介绍完一些知识点后,再理解一下主角“事件循环机制”
我们在前面说了,浏览器会通过渲染主线程去执行JS
在最开始的时候,渲染主线程会进入一个无限的循环中
每一次的循环,都会检查一下消息队列中是否存在任务。 如果存在任务,就取出第一个任务执行,执行完一个后进入下一次循环; 如果没有,就进入等待态(休眠)
其他所有线程(包括其他进程的线程)可以随时向消息队列添加任务,如果主线程是等待态,会将其唤醒以继续循环拿取任务执行。
这种过程,也就被称为 事件循环(消息循环)
在上面的过程中,我们先简单的将消息队列理解成一个队列(虽然有具体划分)。 而队列的特性是先进先出,比如我们按顺序执行代码,分别遇到了 加法任务、输出任务、乘法任务。 那他们依次入队,渲染主线程循环获取任务也是按照这个顺序去执行的
宏任务和微任务
在上面为了便于简单的理解,说是当成一个队列,其实不是的。 JS中用来存储代执行回调函数的队列可以分为2种不同的队列,那就是 宏队列 和 微队列。 顾名思义就是分别用来保存待执行的宏任务和微任务(回调)。
常见的宏任务包括:
setTimeout
setInterval
script(整体代码)
I/O操作
等等
微任务包括:
Promise
Mutation
等等
既然会划分成2个队列,那肯定是要在JS执行时区别对待它们的。 JS引擎首先必须先执行所有的初始化同步任务, 在每次准备取出第一个宏任务执行前,都要看看有没有微任务,要一个个取出来执行。 当该宏任务执行完毕后,会检查其中的微任务队列,如果没有,那就直接执行下一个宏任务,如果不为空,那就依次执行微任务,执行完毕再执行下一个宏任务。
所以引入微任务的初衷是为了解决异步回调的问题。(其实我们可以理解为 微任务的优先级比较高,根据优先级调度算法,调度时会选优先级最高的进行调度执行)
即然说到优先级,就必须要提一下。
任务本身是没有优先级的,都是遵循先来先服务算法。 但是 消息队列是有优先级的。 也就是上面我们所说的 微队列比宏队列优先级高。所以每执行一次宏任务,都要看看有没有微任务的存在。
但随着浏览器复杂的提升,W3C似乎不再采用宏队列的说法。 而是至少分为了 延时队列、交互队列、微队列。 (它们优先级是从低到高的,微队列优先级最高)。具体内容可能还需要看一下官方解释。
如果我们想把一个函数添加到微队列,可以这么写
Promise.resolve().then(函数)
基本的介绍就结束了,应该差不多可以理解这些概念了。接下来可以看一道简单的题
<h1>Eric is handsome</h1>
<button>change</button><script>var h1 = document.querySelector('h1');var btn = document.querySelector('button');// 死循环指定时间function delay(duration){var start = Date.now();while(Date.now() - start < duration) {}}btn.onclick = function() {h1.textContent = "Eric真帅";delay(3000);}
</script>
对于以上代码,当我们点击按钮后,会发生什么呢?
实际上,点击完按钮后,需要经过3秒,h1的文本才会发生变化。
因为对于渲染主线程而言,运行解析JS代码以后,会用交互线程去监听按钮的点击事件。 (假设我们在某一个时刻点击了它,此时消息队列中没有其他任务)
那交互线程会将这个function作为一个任务,假设记为fn,添加至消息队列中。 渲染主线程会被唤醒从而调用fn任务。 所以可以执行function里面的代码了。 首先是h1.textContent = “Eric真帅”,fn任务会产生一个绘制任务(也就是改变h1文本),那这个绘制任务就会到消息队列中进行排队,此时fn任务继续执行到下一行 delay(3000),也就是被阻塞了3秒。3秒后,fn执行完毕,进行循环,这时候获取了消息队列中的绘制任务,调度执行,文本发生改变。
如果有帮助的话,可以点赞收藏哦~~~
相关文章:

事件循环机制(Event Loop)和宏任务(macro-tast)微任务(micro-tast),详细讲解!!!
“事件循环机制” 和 “宏任务微任务” 也是前端面试中常考的面试题了。首先,要深刻理解这些概念的话,需要回顾一些知识点。知识点回顾1、进程与线程进程。 程序运行需要有它自己的专属内存空间,可以把这块内存空间简单的理解为进程每个应用至…...
mysql基础操作3
查询襄阳的员工姓名和性别,性别要求显示为 男 女SELECT ename,(CASE WHEN sexF THEN 女 ELSE 男 END)sexFROM empWHERE jiguan襄阳查询所有的订单,显示订单日期 订单数量 订单状态SELECT saleDate,salesQuantity,(CASE WHEN saleState1 THEN 新建 WHEN s…...

【Web安全】PHP安全
一、文件包含漏洞严格来说,文件包含就是代码注入的一种。代码注入,其原理就是注入一段用户能控制的脚本或代码并让服务器端执行。代码注入的典型代表就是文件包含。文件包含可能会出现在JSP、PHP、ASP等语言中,常见函数如下:PHP&a…...

双向链表+循环链表
循环链表双向链表 循环链表 循环链表是头尾相接的链表(即表中最后一个结点的指针域指向头结点,整个链表形成一个环)(circular linked list) **优点:**从表中任一结点出发均可访问全部结点 循环链表与单链表的主要差别当链表遍历时,判别当前…...

Java程序的逻辑控制
一、顺序结构 顺序结构比较简单,如果我们按照代码书写的顺序一行一行执行,将会是这样的: System.out.println("aaa"); System.out.println("bbb"); System.out.println("ccc"); // 运行结果 aaa bbb ccc 如…...
BUCTOJ - 2023上半年ACM蓝桥杯每周训练题-1-A~K题C++Python双语版
文章目录BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题CPython双语版前言问题 A: 1.2 神奇兔子数列题目描述输入输出解题思路AC代码CPython问题 B: 1.3 马克思手稿中的数学题题目描述输入输出解题思路AC代码CPython问题 C: 1.4 爱因斯坦的阶梯题目描述输入输出解题思路…...

存储的本质-学习笔记
1 经典案例 1.1 数据的流动 一条用户注册数据流动到后端服务器,持久化保存到数据库中。 1.2 数据的持久化 校验数据的合法性修改内存写入存储介质2 存储&数据库简介 2.1 存储系统特点 性能敏感、容易受硬件影响、存储系统代码既“简单”又“复杂”。 2.2 数…...

新一代骨传导机皇重磅发布:南卡Neo骨传导运动耳机,性能全面提升
近日,中国最强骨传导品牌NANK南卡发布了最新一代骨传导耳机——南卡Neo骨传导耳机!该款耳机与运动专业性更强的南卡runner Pro4略微不同,其主要定位于轻运动风格,所以这款耳机的音质和佩戴舒适度达到了令人咂舌的地步!…...
Hbase Schema设计与数据模型操作
一、Hbase Schema设计 1,Schema 创建 使用 Apache HBase Shell 或使用 Java API 中的 Admin 来创建或更新 HBase 模式。 Configuration config HBaseConfiguration.create(); Admin admin new Admin(conf); TableName table TableName.valueOf("myTable&…...

微电影广告有哪些传播优势?
微电影广告是在基于微电影的模式下发展而来的,是伴随着当下快节奏、碎片化的生活方式而诞生的新兴广告表现形式。微电影广告凭借其具备的独特传播优势以及时代特征成为广大企业主塑造企业品牌形象的主要方式。那么,微电影广告究竟有哪些传播优势…...

html基础(列表(ul、ol、dl)、表格table、表单(input、button、label)、div和span、空格nbsp)
1无序列表<ul>和有序列表<ol>1.1无序列表<ul><!-- 无序列表 --><ul><li>吃饭</li><li>睡觉</li><li>打豆豆</li></ul>1.2有序列表<ol><!-- 有序列表 --><ol><li>吃饭</li…...
uniapp常用标签
view ~~ 视图容器类似于传统html中的div,用于包裹各种元素内容<view><text>hh</text> </view>scroll-view ~~可滚动视图区域scroll-x 允许横向滚动scroll-y 允许纵向滚动scroll-top 设置竖向滚动条位置,可以一键回到顶部refresh…...
《数字中国建设整体布局规划》发布,推进IPv6部署和应用是重点
近日,中共中央、国务院印发了《数字中国建设整体布局规划》(以下简称《规划》),并发出通知,要求各地区各部门结合实际认真贯彻落实。 《规划》指出,建设数字中国是数字时代推进中国式现代化的重要引擎&…...

【Java】 异步调用实践
本文要点: 为什么需要异步调用CompletableFuture 基本使用RPC 异步调用HTTP 异步调用编排 CompletableFuture 提高吞吐量BIO 模型 当用户进程调用了recvfrom 这个系统调用,kernel 就开始了 IO 的第一个阶段:准备数据。对于 network io 来说…...

园区智慧能源管理系统
实现对园区的用能情况实时、全方位监测,重点设备进行数据自动采集并智能统计、分析,根据需要绘制各种趋势曲线、能源流向图和分析报表。将物联网、大数据与全过程能源管理相融合,提供全生命周期的数字化用能服务,实现用能的精细化…...

基于卷积神经网络CNN的分类研究,基于卷积神经网络的手写体识别
目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 卷积神经网络CNN手写体识别 基本结构 主要参数 MATALB代码 结果图 展望 背影 现在生活,各种人工智能都要求对图像拥有识别…...

mybatis的增删改查运用
目录 一、总览图 二、运用 一、总览图 代码总览图 数据库总览图 二、运用 数据库的一张表对应一个封装类,一个mapper接口,一个mapper.xml文件, 一个实现类。表中的增删改查都在里面编写 但是配置xml文件整个数据库只要一个就好了 1.…...

centos8安装docker运行java文件
本文由个人总结,如需转载使用请标明原著及原文地址 这里是基于我前一篇搭的centos8服务器做的,如果yum baseos源或appstream源有问题可以去看看前一篇 https://blog.csdn.net/qq_36911145/article/details/129263830 1.安装docker 1.1配置docker yum…...

Docker容器化部署.net core API
1.为API集成Docker环境。(VS自带,傻瓜式操作) 1.1 点击项目,右键,添加,选择Docker支持 1.2 找到项目根目录中的Dockerfile文件,这是VS刚刚帮我们自动生成的。进入和做如图标红地方修改。 把文…...
springcloud 服务调用feign、熔断hystrix、网关gateway
回归cloud的学习,对于springcloud的架构与原理以及性能的分析我们都在之前的文章里写过:springcloud架构的认识我们之前测试过eureka服务注册功能,它能很好的保存服务之间的通讯关系,是维系微服务通讯网之间的电话本,同…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...