事件循环机制(Event Loop)和宏任务(macro-tast)微任务(micro-tast),详细讲解!!!

news2024/12/25 9:04:56

“事件循环机制” 和 “宏任务微任务” 也是前端面试中常考的面试题了。

首先,要深刻理解这些概念的话,需要回顾一些知识点。

知识点回顾

1、进程与线程

进程。

程序运行需要有它自己的专属内存空间,可以把这块内存空间简单的理解为进程

每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。

线程。

线程是CPU的基本调度单位,是程序执行的一个完整流程。

一个进程至少有一个线程,所以在进程开启后会自动创建一个线程来运行代码,该线程称之为 主线程

如果程序需要同时执行多块代码,主线程就会开启更多的线程来执行代码,所以一个进程中可以包含多个线程。

简单总结一些它们的关系:

  • 一个进程中一般至少有一个运行的线程——主线程

  • 一个进程中也可以同时运行多个线程

  • 多个进程之间的数据是不能同时直接共享的

那浏览器有哪些进程与线程呢?

浏览器内部的工作其实极为复杂,它是多进程多线程的。且为了避免相互影响,它会自动启动多个进程。

比如,我们可以在浏览器任务管理器查看一下所有进程。

其中,最主要的进程有:

  1. 浏览器进程

主要负责界面显示、用户交互、子进程管理等。浏览器进程内部会启动多个线程处理不同的任务。

  1. 网络进程

负责加载网络资源。网络进程内部会启动多个线程来处理不同的网络任务

  1. 渲染进程

渲染进程启动后,会开启一个 渲染主线程,主线程负责执行 HTML、CSS、JS代码

默认情况下,浏览器会为每一个标签页开启一个新的渲染进程,以保证不同的标签页之间不互相影响。

2、JS是单线程还是多线程?

JS肯定是单线程的。

如果是多线程会发生什么? 如果JS是多线程,那当两个线程同时对dom进行操作,一个是添加事件,一个是删除dom,要怎么处理? 所以为了避免这种情况,JS选择只用一个主线程来执行代码以保证一致性。

3、怎么去理解JS的异步?

上面写到JS是单线程的,它运行在浏览器的渲染主线程中,且渲染主线程有且仅有一个。 但是它却有很多任务,比如渲染页面、执行JS都包含在内。

那如果不使用异步,而是同步的方式,就极有可能造成主线程的阻塞,那其他任务就无法执行了,一方面消耗时间,另一方面页面又没法及时更新,很容易有卡死现象。

所以浏览器采用异步方式。 具体做法其实就是, 比如一些任务发生了,假设现在遇到了计时器,主线程会将任务交给其他线程处理,自己立马结束这个任务,转而执行后续代码。 而等其他线程完成后,将事先传递的回调函数包装成任务,再加入到消息队列的末尾排队,等待主线程的调度执行。

在这种异步模式下,浏览器就可以避免阻塞。

这一段解释涉及到操作系统的进程调度问题和我们所要理解的事件循环机制。暂时看不懂的,可以先往下看。

4、进程调度

进程调度的知识点稍多,比如抢占式调度,非抢占式调度,先来先服务,优先级调度等等。

我们这里就简单介绍一下先来先服务(FCFS)

它的算法思想其实就是从“公平”的角度来考虑的 (我们可以理解成 排队买东西,先来排队的优先买)。所以它的算法规则,其实是按照 作业/进程 到达的先后顺序进行服务。 它是一种非抢占式算法 (可以理解成 “不允许你插队”),它不会导致 “饥饿”现象(也就是一直轮不到执行,苦苦等待),因为只要排队终有一天会轮到它的。

事件循环机制

介绍完一些知识点后,再理解一下主角“事件循环机制”

我们在前面说了,浏览器会通过渲染主线程去执行JS

  1. 在最开始的时候,渲染主线程会进入一个无限的循环中

  1. 每一次的循环,都会检查一下消息队列中是否存在任务。 如果存在任务,就取出第一个任务执行,执行完一个后进入下一次循环; 如果没有,就进入等待态(休眠)

  1. 其他所有线程(包括其他进程的线程)可以随时向消息队列添加任务,如果主线程是等待态,会将其唤醒以继续循环拿取任务执行。

这种过程,也就被称为 事件循环(消息循环)

在上面的过程中,我们先简单的将消息队列理解成一个队列(虽然有具体划分)。 而队列的特性是先进先出,比如我们按顺序执行代码,分别遇到了 加法任务、输出任务、乘法任务。 那他们依次入队,渲染主线程循环获取任务也是按照这个顺序去执行的

宏任务和微任务

在上面为了便于简单的理解,说是当成一个队列,其实不是的。 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执行完毕,进行循环,这时候获取了消息队列中的绘制任务,调度执行,文本发生改变。

如果有帮助的话,可以点赞收藏哦~~~

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

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

相关文章

计算机求解满足三角形各边数字之和相等的数字填充

圆圈处不重复的填入1至9&#xff0c;使得每条边的四个数字相加的总和相等。 求解思路&#xff1a; 数组中存放1到9的数字&#xff0c;每次随机交换两个数字&#xff0c;构建出新的数字组合&#xff0c;计算这个数字组合是否符合要求。 #include <stdio.h> #include <…

SpringBoot实现Excel导入导出,简单好用

EasyPoi简介 POI是Java操作MicroOffice&#xff08;如对Excel的导入导出&#xff09;的一个插件。POI的全称是&#xff08;Poor Obfuscation Implementation&#xff09;&#xff0c;POI官网地址是 http://poi.achache.org/index.html 。 EasyPoi对POI进行了优化&#xff0c;…

SVN vs Git 不是技术之争,而是生态之争

师父&#xff08;80 后老员工&#xff09;&#xff1a;小吉啊&#xff0c;我看我们文档越来越多了&#xff0c;手动管理起来很费劲。你去搞一个 SVN 来用一哈&#xff0c;做个版本控制&#xff0c;这样大家都方便。 徒弟&#xff08;95 后新力量&#xff09;&#xff1a;师父啊…

电脑快捷方式删除文件后四种找回方法

快捷指令是一种用作替代快捷键操作的技术。也可以称为“快捷键”&#xff0c;“快捷方式”或“快捷键序列”&#xff0c;它们允许用户在非常快速和方便的方式建立特定操作序列&#xff0c;这对于执行重复性或提高效率非常有用。通过使用快捷指令&#xff0c;您可以执行快速复制…

pod进阶

一.资源限制当定义 Pod时可以选择性地为每个容器设定所需要的资源数量。最常见的可设定资源是CPU和内存大小&#xff0c;以及其他类型的资源。当为 pod 中的容器指定了request资源时&#xff0c;调度器就使用该信息来决定将Pod 调度到哪个节点上。当还为容器指定了limit资源时&…

C++Primer16.1.6节练习

练习16.28&#xff1a; 简易的shared_ptr代码如下 #include <iostream> #include <vector> #include <list> using namespace std;//shared_ptr模板 template<typename T>class SharedPtr {friend SharedPtr<T>& MakeShared(T* t); public…

docker部署MySQL主从服务

一.主从同步流程关于MySQL主从复制主要同步的是binlog日志&#xff0c;涉及到三个线程&#xff0c;一个运行在主节点&#xff08;log dump thread&#xff09;&#xff0c;其余两个(I/O thread, SQL thread)运行在从节点&#xff0c;如下图所示:当主库数据发生变更时&#xff0…

【JavaWeb】EL表达式(191-202)

191.EL表达式-什么是EL表达式&#xff0c;以及它的作用 什么是 EL 表达式&#xff0c;EL 表达式的作用? EL 表达式的全称是&#xff1a;Expression Language。是表达式语言。 EL 表达式的什么作用&#xff1a;输出&#xff0c;EL 表达式主要是代替 jsp 页面中的表达式脚本在…

第三章 opengl之纹理

OpenGL纹理纹理环绕方式纹理过滤多级渐远纹理加载和创建纹理stb_image.h生成纹理纹理的应用纹理单元纹理 用stb_image.h库&#xff0c;原先用SOIL库也可以实现。 可以为每个顶点添加颜色来增加图形的细节。但是想得到一个真实的图形&#xff0c;需要足够多的顶点&#xff0c;…

定时任务调度方案——Xxl-Job

定时任务调度方案 随着系统规模的发展&#xff0c;项目的组织结构以及架构越来越复杂&#xff0c;业务覆盖的范围越来越广&#xff0c;定时任务数量日益增多&#xff0c;任务也变得越来越复杂&#xff0c;尤其是为了满足在用户体量日历增大时&#xff0c;系统能够稳定运行&…

汽车改色避坑指南

关于汽车改色&#xff0c;真的不是只看颜色看价格那么简单。 如何选择一家靠谱的改色店&#xff1f;要看这家店是否正规&#xff0c;是否有完备的售后和质保流程&#xff0c;后续剐蹭、磕碰、划痕是否可以修复&#xff1f;是否提前告知注意事项&#xff0c;以及改色后备案流程&…

浅谈车载测试之智能座舱人机交互

1、引言 目前&#xff0c;汽车不仅在动力源、驱动方式和驾驶体验上发生了变化&#xff0c;驾驶舱也告别了传统的枯燥机械和电子空间&#xff0c;智能化水平飙升&#xff0c;成为继家庭和办公室以外人们生活之后的“第三空间”。通过人脸&#xff1b;指纹识别、语音 / 手势交互…

【线程-J.U.C】

Lock J.U.C最核心组件&#xff0c;Lock接口出现之前&#xff0c;多线程的并发安全只能由synchronized处理&#xff0c;但java5之后&#xff0c;Lock的出现可以解决synchronized的短板&#xff0c;更加灵活。 Lock本质上是一个接口&#xff0c;定义了释放锁&#xff08;unlock&…

解决:centos7如何解决网络不可达和wget: 无法解析主机地址 “downloads.mysql.com”

遇到此类问题可能会有多重解决方法&#xff0c;需要一个一个的去排除。 1、查看自己的网络设置是不是设置的NAT模式&#xff0c;设置完成后再去ping一下网络地址。 2、ping一下百度看能不能拼成功&#xff0c;下图是ping成功的样式。&#xff08;如果不行继续往下走&#xff0…

牛客sql题目练习

Sql3描述 题目&#xff1a;现在运营需要查看用户来自于哪些学校&#xff0c;请从用户信息表中取出学校的去重数据。 示例:user_profile iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543female20北京大学Beijing42315femal…

PowerShell攻击指南

文章目录一&#xff1a;PowerShell简介1.1&#xff1a;基本概念1.2&#xff1a;执行策略与绕过1.3&#xff1a;常用命令二&#xff1a;PowerSploit2.1&#xff1a;PowerSploit安装2.2&#xff1a;PowerSploit攻击实战2.2.1&#xff1a;直接shellcode反弹meterpreter shell2.2.2…

【C/C++每日一练】总目录(不断更新中...)

C/C 2023.03 20230303 1. 字符串相乘 ★★ 2. 单词拆分 II ★★★ 3. 串联所有单词的子串 ★★★ 20230302 1. 个位数是6&#xff0c;且能被3整除的五位数共有多少个&#xff1f; ☆ 2. 不同方式求n的阶乘 ★ 3. 报数游戏 ★☆ 20230301 1. 冒泡排序法排序 ★ …

视频号频出10w+,近期爆红的账号有哪些?

回顾2月&#xff0c;视频号持续放出大动作&#xff0c;不仅进行了16小时不间断的NBA全明星直播&#xff0c;还邀请国际奥委会入驻&#xff0c;分享奥运的最新资讯。视频号成为越来越多官方机构宣传推广的有效渠道。官方积极入驻&#xff0c;内容创作生态也在同步繁荣发展&#…

中村成洋《垃圾回收的算法与实现》PDF 读书笔记

观前提醒 为了能够锻炼自己&#xff0c;我会查阅大量外文不停的修改内容&#xff0c;少部分会提示成中文。 可能有误&#xff0c;请见谅 提示&#xff1a;若是觉得阅读困难&#xff0c;可以看如下内容 脚本之家可获取&#xff0c;若失效可私信浏览器的沙拉查词扩展&#xf…

Shell脚本学习指南 - 第二章入门篇

shell脚本的第一行#! #! /bin/awk -f 内核会扫描文件开头的#!后面内容&#xff0c;跳过所有空白符号&#xff0c;寻求可以用来执行程序的解释器的full path和option&#xff08;option后面的空格会识别&#xff09; ; shell用分号隔开多条语句 & 后台执行该命令&#xff…