js 中的 Event Loop 以及 宏任务 与 微任务

news2025/2/24 6:47:32

目录

  • 前言
    • 1、JS 的 执行引擎 与 执行环境
    • 2、js 是单线程的
  • 一、事件循环(Event Loop)
  • 二、任务队列
  • 三、宏任务 与 微任务
    • 1、宏任务
    • 2、微任务
    • 3、宏任务与微任务的运行机制
  • 四、Event Loop 实例
    • 案例一
    • 案例二


前言

1、JS 的 执行引擎 与 执行环境

简单来说,为了让 JavaScript 运行起来,要完成两部分工作(当然实际比这复杂的多):

  • Engine(执行引擎):编译并执行 JavaScript 代码,完成内存分配、垃圾回收等。
  • Runtime(执行环境):为 JavaScript 提供一些对象或机制,使它能够与外界交互。

在 JavaScript 运行的时候,JavaScript Engine 会创建和维护相应的堆(Heap)和栈(Stack),同时通过 JavaScript Runtime 提供的一系列 API(例如:setTimeout、XMLHttpRequest 等)来完成各种各样的任务。

2、js 是单线程的

进程:
- 资源分配的最小单位。
- 指在系统中正在运行的一个应用程序。
- 程序一旦运行就是进程。

线程:
- 程序执行的最小单位。
- 系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。

JavaScript 是一种单线程的编程语言,只有一个调用栈,决定了它在同一时间只能做一件事情。

在 JavaScript 的运行过程中,真正负责执行 JavaScript 代码的始终只有一个线程,通常被称为主线程,各种任务都会用排队的方式来同步执行。

然而 JavaScript 却又是一个非阻塞(Non-blocking)、异步(Asynchronous)、并发式(Concurrent)的编程语言,这就得说说 JavaScript 的事件循环(Event Loop)机制了。


一、事件循环(Event Loop)

事件循环(Event Loop) 是让 JavaScript 做到既是单线程,又绝对不会阻塞的核心机制,也是 JavaScript 并发模型(Concurrency Model)的基础,是用来协调各种事件、用户交互、脚本执行、UI 渲染、网络请求等的一种机制。简而言之——Event Loop 是 JS 实现异步的一种机制

Event Loop 包含 2 种:一种存在于 Browsing Context 中,还有一种在 Worker 中。

二者的运行是独立的。也就是说,每一个 JavaScript 运行的“线程环境”都有一个独立的 Event Loop,每一个 Web Worker 也有一个独立的 Event Loop。


二、任务队列

Event Loop(事件循环)是通过 任务队列 的机制来进行协调的。

任务队列 的特点:

  • 一个 事件循环 中可以有一个或者多个 任务队列,一个 任务队列 便是一系列有序 任务 的集合。
  • 每个 任务 都有一个 任务源,同一个 任务源 的 任务 必须放到同一个 任务队列 中。
  • setTimeout、Promise 等 API 便是 任务源,而进入 任务队列 的是他们指定的具体执行任务。

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

  • 在此次 tick 中选择最先进入队列的任务(oldest task),如果有则执行(一次);
  • 检查是否存在 Microtasks,如果存在则不停地执行,直至清空 Microtasks Queue;
  • 更新 render;
  • 主线程重复执行上述步骤。

在上述 tick 的基础上需要了解几点:

  • JS 分为同步任务和异步任务;
  • 同步任务都在主线程上执行,形成一个执行栈;
  • 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件;
  • 一旦执行栈中的所有同步任务执行完毕(此时 JS 引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。
    在这里插入图片描述

三、宏任务 与 微任务

1、宏任务

(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。

浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染——(macro)task->渲染->(macro)task->...

宏任务包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel 和 setImmediate(Node.js 环境)。

2、微任务

microtask 可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。

所以它的响应速度相比setTimeout(setTimeout 是 task)会更快,因为无需等渲染。也就是说,在某一个 macrotask 执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。

微任务包含:Promise、async/await、Object.observe、MutationObserver 和 process.nextTick(Node.js 环境)。


3、宏任务与微任务的运行机制

在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下:

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后 GUI 线程接管渲染
  • 渲染完毕后,JS 线程继续接管,开始下一个宏任务(从事件队列中获取)
    在这里插入图片描述

四、Event Loop 实例

案例一

console.log(1);
 
setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});
 
new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
})
 
setTimeout(() => {
  console.log(6);
})
 
console.log(7);

// 输出结果:1 4 7 5 2 3 6 

解析:
执行全局同步代码(promise中在resolve或reject前的也算) 所以输出:1,4,7。
执行微队列代码 此时的微队列中的任务为Promise中的resolve(5)则输出:5。
执行宏队列中的队首任务(注意只执行一个宏任务),此时的队首任务为代码中第一个setTimeOut,则输出了:2。在执行这个任务时又产生了一个新的微任务。
执行新产生的微队列中的任务,所以输出了:3。
微任务队列为空,宏队列中还有一个任务,于是输出:6。

案例二

const foo = {
	bar: function () {
		return this.baz;
	},
	baz: 3
}
const fn = foo.bar;
console.log(fn());// undefined




【参考文章】
深入理解 JavaScript Event Loop-阿里 CCO 体验技术专刊首发
js中的宏任务与微任务
JavaScript 运行机制详解:再谈Event Loop

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

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

相关文章

SpringCloud微服务(八)——OpenFeign服务调用

OpenFeign服务调用 SpringCloud github官网:https://github.com/spring-cloud/spring-cloud-openfeign Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解,比如&#xf…

基于java+springboot+mybatis+vue+elementui的人职匹配推荐系统

项目介绍 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势,对于人职匹配推荐系统当然也不能排除在外,随着网络技术的不断成熟,带动了人职匹配推荐系统,它彻底改变…

分享一下前几个月我做的超炫的登录页面

先给大家看看登录页面的效果演示 这个登录页面分为三个部分(页面切换:连续按五次V,大小写都可以) 第一个(最初的鱼儿游动页面) 登录、切换页面、和鱼儿游动这个页面的代码就不放在这里了,这个虽…

RabbitMQ 入门案例项目

写在前面 本文不作消息队列的实现原理、异步处理优劣、rabbitmq安装说明、消息工作模式等内容分析,只讲述rabbitmq实际开发中的步骤说明,帮助同学快速上手体验消息队列的使用。 本文使用SpringAMQP,并非rabbitmq官方文档上的原生http请求连…

Jupyter notebook在超算平台上使用的详细教程

Jupyter Notebook 的本质是一个 Web 应用程序,便于创建和共享文学化程序文档,支持实时代码,数学方程,可视化和 markdown。 用途包括:数据清理和转换,数值模拟,统计建模,机器学习等等…

LeetCode 数据结构与算法:最大子数组和

打开我的题库,调为简单难度。 计算最大子数,直接给我难住。 报错铺满屏幕,凝望没有思路。 缝缝补补做出,击败零个用户。 翻阅评论找补,令我勃然大怒。 打开思维第一步,编写代码求数组, …

报错解决:Process finished with exit code -1073741819 (0xC0000005)

简单记录一下程序异常终止,抛出 Process finished with exit code -1073741819 (0xC0000005) 的解决方法。 一、程序中文件位置错误/缺少文件 位置错误1:如果使用相对路径的话,推荐换成绝对路径进行排查。位置错误2:如果使用了o…

CAN总线协议测试拓扑图

记录测试CAN总线协议, CAN总线目前主要应用在汽车。 记录在PC使用USB-CAN连接测试

Talk预告 | Salesforce AI研究院研究科学家徐嘉诚:文本生成中的结构化解码

本期为TechBeat人工智能社区第457期线上Talk! 北京时间11月23日(周三)20:00,Salesforce AI研究院研究科学家——徐嘉诚的Talk将准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “文本生成中的结构化解码”,届时将详细讲解…

学会用数据分析汇报工作,升职加薪指日可待

你是否每天的八小时工作时长,分成八瓣用,却仍被领导安排众多工作?明明做了很多事,领导依旧认为工作量不饱和?这样的现象在职场中早已司空见惯,不足为奇了,但是究其原因是什么呢?工作…

Android App网络通信中通过runOnUiThread快速操纵界面以及利用线程池Executor调度异步任务实战(附源码 简单易懂)

运行有问题或需要源码请点赞关注收藏后评论区留言私信~~~ 一、通过runOnUiThread快速操纵界面 因为Android规定分线程不能够直接操纵界面,所以它设计了处理程序工具,由处理程序负责在主线程和分线程之间传递数据,如果分线程想刷新界面&#…

精心整理16条MySQL使用规范,减少80%问题

1. 禁止使用select * 阿里开发规范中,有这么一句话: **select *** 会查询表中所有字段,如果表中的字段有更改,必须修改SQL语句,不然就会执行错误。 查询出非必要的字段,徒增磁盘IO和网络延迟。 2. 用小表…

小学生python游戏编程arcade----敌人精灵上方显示方框及子弹显示问题

小学生python游戏编程arcade----敌人精灵上方显示方框及子弹显示问题前言1、敌人精灵上方显示方框1.1 修改enemy_tank类1.2 引用1.3 效果图2、调整方法2.1 类方法2.2 类的引用2.3 效果图2.4 大小位置调整后3、子弹过线自动消失3.1 子弹的更新中3.2 原因查到,把以下代…

day11 多级缓存

day11 多级缓存 1、什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: 请求要经过 Tomcat 进行处理,Tomcat 的性能成为整个系统的瓶颈Red…

数字孪生助力轨道交通安保可视化应用

截至2020年12月31日,全国(不含港澳台)共有44个城市开通运营城市轨道交通线路233条,运营里程7545.5公里,车站4660座,完成客运量175.9亿人次,进站量109.1亿人次。针对轨道交通地铁站内日常监测、事…

牛客网语法篇练习分支控制(一)

1.据说智商140以上者称为天才,KiKi想知道他自己是不是天才,请帮他编程判断。输入一个整数表示一个人的智商,如果大于等于140,则表明他是一个天才,输出“Genius”。 while True:try:a int(input())if a >140:print…

云原生加速器企业维格表创始人陈霈霖:提供人人可用的数字化转型全新方案,真正驱动组织创新

看上去是像Excel一样的在线协同表格,却能把文件、表格、图片、视频、填表单等变换出各种视图,它能帮助你高效方便的管理各种零碎的信息和数据;也能根据你的想法DIY各种功能,5分钟即可搭建一个适合自己的文档管理系统,实…

C#上位机系列(1)—项目的建立

本文是讲解C#.net平台的Winform框架下的第一个内容,手把手介绍项目的创建方式以及一些写软件时常用的功能。之前写过一篇关于示波器的比较抽象,本文讲解从零开始的每一个步骤。 VS2022以及C#.net平台的Winform框架自行百度下载。 1.创建一个新的项目 …

智慧经营| 物业数字化管理系统

无论小区、公寓还是豪华区,总是少不了物业的身影,通过物业可以为住户解决许多事情,比如物业报事、物业维修、便民服务、送水上门、房屋租赁、投诉等,但小区内公告栏没人看、挨家挨户的去通知效率低、且无法全面完善管理区域内的所…

Linux操作系统~尝试自己制作并使用动静态库

目录 1.动态库和静态库到底是什么 (1).静态库 vs 动态库 (2).动态链接和静态链接的优劣 (3).ldd指令 2.自己制作静态库 (1).打包静态库 (2).ar指令 3…