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

简述js的事件循环以及宏任务和微任务

前言

JavaScript中,任务被分为同步任务和异步任务。

  • 同步任务:这些任务在主线程上顺序执行,不会进入任务队列,而是直接在主线程上排队等待执行。每个同步任务都会阻塞后续任务的执行,直到它自身完成。常见的同步任务包括页面的初始化、DOM操作和某些计算任务。
  • 异步任务:与同步任务不同,异步任务不直接进入主线程执行,而是被放入任务队列(task queue)中。只有当主线程空闲时,才会从任务队列中取出任务来执行。异步任务不会阻塞主线程的执行。根据任务类型,异步任务又被分为宏任务微任务

一、事件循环是什么?

  • JavaScript 的事件循环(Event Loop)是其运行时环境(如浏览器或 Node.js处理异步操作和回调的一种机制。它允许 JavaScript 在不阻塞单线程执行的情况下,响应用户交互、处理网络请求、定时器回调等异步事件

二、事件循环的基本基本概念和工作原理

1. 调用栈(Call Stack

JavaScript 引擎有一个调用栈,用于跟踪函数调用的顺序。当一个函数调用发生时,它会被推入调用栈中。当函数执行完毕后,它会被从调用栈中弹出。

2. 任务队列(Task Queue):

当异步操作(如 setTimeout、setInterval、DOM 事件、Promise.resolve().then() 等)完成时,它们会生成一个任务(task)(简单理解为任务就是回调函数),并将这个任务放入相应的任务队列中等待执行。

  • 这些任务队列包括宏任务队列(macrotask queue)和微任务队列(microtask queue
  • 宏任务队列主要存放 script(全局任务)、setTimeoutsetIntervalsetImmediateNode.js 环境)等;微任务队列主要存放 Promise 的回调函数、MutationObserver(浏览器环境)等。
3. 事件循环:

事件循环的基本顺序是:

  1. 当调用栈为空时(即没有正在执行的函数),事件循环会查看任务队列。
  2. 事件循环会率先查看微任务队列。如果微任务队列中有任务,它会将任务逐个取出并执行,直到微任务队列为空。
  3. 然后,事件循环会查看宏任务队列。如果宏任务队列中有任务,它会将任务取出并执行。在执行宏任务的过程中,可能会产生新的微任务,这些微任务会被添加到微任务队列的末尾。
  4. 当一个宏任务执行完毕后,事件循环会再次查看微任务队列并执行其中的任务,这个过程会一直重复,直到所有的任务都被执行完毕。
  5. 这个过程会持续进行,形成了一个循环,这就是所谓的“事件循环”。

三、宏任务和微任务?

  • JavaScript的事件循环中,任务的执行被分为两种主要的类别:宏任务(MacroTask)和微任务(MicroTask)。这两种任务类型在事件循环中的处理顺序和方式有所不同。
1. 宏任务(MacroTask

宏任务通常包括:

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediateNode.js 环境)
  • I/O
  • UI渲染(浏览器会在每次事件循环结束后进行UI渲染)
  • MessageChannel(消息通道)
  • postMessage(一些HTML5 API使用)
  • requestAnimationFrame(浏览器用于定时执行动画)

宏任务创建后会被放入宏任务队列中,JavaScript引擎会在当前执行栈清空后,从宏任务队列中取出队首任务执行。

2. 微任务(MicroTask

微任务通常包括:

  • Promise.then()Promise.catch()
  • MutationObserverHTML5API,用于监听DOM变更)
  • process.nextTickNode.js环境)
    与宏任务不同,微任务是在当前宏任务执行完成后立即执行的。在JavaScript引擎执行完一个宏任务后,它会先查看微任务队列,并执行所有的微任务,直到微任务队列为空。然后,它会继续取出并执行下一个宏任务。这个过程会不断重复,形成JavaScript的事件循环。

执行顺序
考虑以下的示例:

javascript
console.log('script start'); // 同步任务  setTimeout(function() {  console.log('setTimeout'); // 宏任务  
}, 0);  Promise.resolve().then(function() {  console.log('promise1'); // 微任务  
}).then(function() {  console.log('promise2'); // 微任务  
});  console.log('script end'); // 同步任务
尽管setTimeout的延迟被设置为0,但它的回调仍然会在所有的微任务之后执行。因此,上述代码的输出顺序为:script start  
script end  
promise1  
promise2  
setTimeout
这是因为当JavaScript引擎执行到setTimeout时,它会将回调函数放入宏任务队列,并继续执行后续的代码。当执行到Promise.then()时,它会将回调函数放入微任务队列。在所有宏任务代码执行完毕后,JavaScript引擎会先执行所有的微任务,然后再从宏任务队列中取出并执行下一个宏任务。

四、练习

  1. 练习一:
  console.log('Start'); // 同步任务// 宏任务1setTimeout(() => {console.log('Timeout callback'); // 同步任务Promise.resolve().then(() => {console.log('Promise 1'); //  微任务1Promise.resolve().then(() => {console.log('Promise 2'); //  微任务2Promise.resolve().then(() => {console.log('Promise 3'); //  微任务3执行完执行下一个宏任务});});});}, 0);// 宏任务2setTimeout(() => {console.log('Timeout222 callback'); // 6}, 0);
  1. 练习二:
  //  开启一个微任务,当dom修改时触发const observer = new MutationObserver(function (mutationsList, observer) {console.log(mutationsList, observer)});const config = { attributes: true, childList: true, subtree: true };console.log('script start'); // 同步任务 1  (function () {console.log('自执行函数 '); // 同步任务 2})()// 宏任务2setTimeout(function () {Promise.resolve().then(function () {var element = document.getElementById('app');observer.observe(element, config);var child = document.getElementById('child');element.innerHTML = '<p>这是一段新的HTML内容。</p>';console.log('promise11'); // 同步任务  Promise.resolve().then(() => {console.log('promise11 callback 1'); // (3) 微任务  });Promise.resolve().then(() => {console.log('promise11 callback 2'); // (3) 微任务  });})console.log('setTimeout'); // 同步任务  }, 0);// 宏任务3setTimeout(() => {console.log(111);})Promise.resolve().then(function () {console.log('promise1'); // 微任务1  Promise.resolve().then(() => {console.log('promise1 callback 1'); // 微任务1-2  });Promise.resolve().then(() => {console.log('promise1 callback 2'); // 微任务 1-3  });}).then(function () {console.log('promise2'); // 微任务2  // 宏任务4setTimeout(() => {console.log('微任务内的宏任务'); // 宏任务队列4Promise.resolve().then(() => {console.log('微任务2 promise callback'); // 微任务队列4 });})Promise.resolve().then(() => {console.log('promise2 callback 1'); // 微任务2-1  });Promise.resolve().then(() => {console.log('promise2 callback 2'); // 微任务2-2  });})console.log('script end'); // 同步任务3// 执行同步任务,当遇到异步宏任务放入宏任务队列,异步微任务放入微任务队列// 所以执行顺序// script start// 自执行函数// script end// promise1// promise1 callback 1// promise1 callback 2// promise2// promise2 callback 1// promise2 callback 2// ---宏任务2// setTimeout// promise11// MutationObserver// promise11 callback 1// promise11 callback 2// ---宏任务3// 111// ---宏任务4// 微任务内的宏任务// 微任务2 promise callback
  1. 练习三:script整体为何是宏任务
// 宏任务一
<script>console.log('script1') // 同步// 宏任务三setTimeout(() => {console.log('setTimeout1');// 宏任务五setTimeout(() => {console.log('setTimeout3');})})// 微任务Promise.resolve().then(() => {console.log('promise1');})
</script>// 宏任务二
<script>console.log('script2') // 同步// 宏任务四setTimeout(() => {console.log('setTimeout2');// 宏任务六setTimeout(() => {console.log('setTimeout4');})})// 微任务Promise.resolve().then(() => {console.log('promise2');})
</script>可以看出来script相当于setTimeOut开启宏任务列表,执行完当前宏任务去执行微任务,微任务执行完毕,执行宏任务二,以此类推所以输出结果:
script1
promise1
script2
promise2
setTimeout1
setTimeout2
setTimeout3
setTimeout4

相关文章:

简述js的事件循环以及宏任务和微任务

前言 在JavaScript中&#xff0c;任务被分为同步任务和异步任务。 同步任务&#xff1a;这些任务在主线程上顺序执行&#xff0c;不会进入任务队列&#xff0c;而是直接在主线程上排队等待执行。每个同步任务都会阻塞后续任务的执行&#xff0c;直到它自身完成。常见的同步任…...

[力扣题解] 797. 所有可能的路径

题目&#xff1a;797. 所有可能的路径 思路 深度搜索 代码 // 图论哦!class Solution { private:vector<vector<int>> result;vector<int> path;// x : 当前节点void function(vector<vector<int>>& graph, int x){int i;// cout <&l…...

【QT八股文】系列之篇章3 | QT的多线程以及QThread与QObject

【QT八股文】系列之篇章3 | QT的多线程 前言4. 多线程为什么需要使用线程池线程池的基础知识python中创建线程池的方法使用threading库队列Queue来实现线程池使用threadpool模块&#xff0c;这是个python的第三方模块&#xff0c;支持python2和python3 QThread的定义QT多线程知…...

基于python flask的web服务

基本例子 from flask import Flask app Flask(__name__) app.route(/)#检查访问的网址&#xff0c;根路径走这里 def hello_world():return hello world#返回hello worldif __name__ __main__:# 绑定到指定的IP地址和端口app.run(host0.0.0.0, port1000, debugTrue)##绑定端…...

HTTP 响应分割漏洞

HTTP 响应分割漏洞 1.漏洞概述2.漏洞案例 1.漏洞概述 HTTP 响应拆分发生在以下情况&#xff1a; 数据通过不受信任的来源&#xff08;最常见的是 HTTP 请求&#xff09;进入 Web 应用程序。该数据包含在发送给 Web 用户的 HTTP 响应标头中&#xff0c;且未经过恶意字符验证。…...

Algoriddim djay Pro Ai for Mac:AI引领,混音新篇章

当AI遇上音乐&#xff0c;会碰撞出怎样的火花&#xff1f;Algoriddim djay Pro Ai for Mac给出了答案。这款专业的DJ混音软件&#xff0c;以AI为引擎&#xff0c;引领我们进入混音的新篇章。 djay Pro Ai for Mac的智能混音功能&#xff0c;让每一位DJ都能感受到前所未有的创作…...

常见算法(3)

1.Arrays 它是一个工具类&#xff0c;主要掌握的其中一个方法是srot&#xff08;数组&#xff0c;排序规则&#xff09;。 o1-o2是升序排列&#xff0c;o2-o1是降序排列。 package test02; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparat…...

集中抄表电表是什么?

1.集中抄表电表&#xff1a;简述 集中抄表电表&#xff0c;又称为远程抄表系统&#xff0c;是一种现代化电力计量技术&#xff0c;为提升电力行业的经营效率和客户服务质量。它通过自动化的形式&#xff0c;取代了传统人工抄水表&#xff0c;完成了数据信息实时、精确、高效率…...

第八届能源、环境与材料科学国际学术会议(EEMS 2024)

文章目录 一、重要信息二、大会简介三、委员会四、征稿主题五、论文出版六、会议议程七、出版信息八、征稿编辑 一、重要信息 会议官网&#xff1a;http://ic-eems.com主办方&#xff1a;常州大学大会时间&#xff1a;2024年06月7-9日大会地点&#xff1a;新加坡 Holiday Inn …...

09.自注意力机制

文章目录 输入输出运行如何运行解决关联性attention score额外的Q K V Multi-head self-attentionPositional EncodingTruncated Self-attention影像处理vs CNNvs RNN图上的应用 输入 输出 运行 链接&#xff08;Attention Is All You Need&#xff09; 如何运行 解决关联性 a…...

时政|杂粮产业

政策支持 《新一轮千亿斤粮食产能提升行动方案&#xff08;2024—2030年&#xff09;》明确&#xff0c;按照“巩固提升口粮、主攻玉米大豆、兼顾薯类杂粮”的思路&#xff0c;因地制宜发展马铃薯、杂粮杂豆等品种&#xff0c;根据市场需求优产稳供。 产地发展 河北省石家庄…...

docker 安装 私有云盘 nextcloud

拉取镜像 # 拉取镜像 sudo docker pull nextcloud运行nextcloud 容器 # 内存足够可以不进行内存 --memory512m --memory-swap6g # 桥接网络 --network suixinnet --network-alias nextcloud \ sudo docker run -itd --name nextcloud --restartalways \ -p 9999:80 \ -v /m…...

第十一届蓝桥杯物联网试题(国赛)

国赛题目看着简单其实还是挺复杂的&#xff0c;所以说不能掉以轻心&#xff0c;目前遇到的问日主要有以下几点&#xff1a; 本次题主要注重的是信息交互&#xff0c;与A板通信的有电脑主机和B板&#xff0c;所以处理好这里面的交互过程很重要 国赛中避免不了会收到其他选手的…...

算法金 | Dask,一个超强的 python 库

本文来源公众号“算法金”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;Dask&#xff0c;一个超强的 python 库 1 Dask 概览 在数据科学和大数据处理的领域&#xff0c;高效处理海量数据一直是一项挑战。 为了应对这一挑战&am…...

Java 说唱歌手

Yo yo yo&#xff0c;欢迎来到Java地带&#xff0c;技术的盛宴开启&#xff0c; 从JDK到JVM&#xff0c;我们构建的是数字世界的奇迹。 Spring Boot启动&#xff0c;微服务架构轻盈起舞&#xff0c; IoC解耦依赖&#xff0c;AOP切面如丝般顺滑。 Maven管理依赖&#xff0c;Gra…...

面试-软件工程与设计模式相关,Spring简介

面试-软件工程与设计模式相关&#xff0c;Spring简介 1.编程思想1.1 面向过程编程1.2 面向对象编程1.2.1 面向对象编程三大特征 1.3 面向切面编程1.3.1 原理1.3.2 大白话&#xff1f;1.3.3 名词解释1.3.4 实现 2. 耦合与内聚2.1 耦合性2.2 内聚性 3. 设计模式3.1 设计模型七大原…...

IDEA中一些常见操作【持续更新】

文章目录 前言善用debugidea中debug按钮不显示自动定位文件【始终选择打开的文件】idea注释不顶格【不在行首】快速定位类的位置【找文件非常快】创建文件添加作者及时间信息快速跳转到文件顶端 底端 前言 因为这些操作偶尔操作一次&#xff0c;不用刻意记忆&#xff0c;有个印…...

java继承使用细节二

构造器 主类是无参构造器时会默认调用 public graduate() {// TODO Auto-generated constructor stub也就是说我这里要用构造器会直接调用父类。它是默认看不到的 &#xff0c;System.out.println("graduate");} 但当主类是有参构造器如 public father_(int s,doubl…...

c++11 标准模板(STL)本地化库 - 平面类别(std::numpunct_byname) 表示系统提供的具名本地环境的 std::numpunct

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 表示系统提供的具名本地环境的 std::numpunct std::numpunct_byn…...

XILINX FPGA DDR 学习笔记(一)

DDR 内存的本质是数据的存储器&#xff0c;首先回到数据的存储上&#xff0c;数据在最底层的表现是地址。为了给每个数据进行存放并且在需要的时候读取这个数据&#xff0c;需要对数据在哪这个抽象的概念进行表述&#xff0c;我们科技树发展过程中把数据在哪用地址表示。一个数…...

vue源码2

vue之mustache库的机理其实是将模板字符串转化为tokens 然后再将 tokens 转化为 dom字符串&#xff0c;如下图 对于一般的将模板字符串转化为dom字符串&#xff0c;这样不能实现复杂的功能 let data {name:小王,age:18 } let templateStr <h1>我叫{{name}},我今年{{ag…...

Android四大组件 Broadcast广播机制

一 概述 广播 (Broadcast) 机制用于进程或线程间通信&#xff0c;广播分为广播发送和广播接收两个过程&#xff0c;其中广播接收者 BroadcastReceiver 是 Android 四大组件之一。BroadcastReceiver 分为两类&#xff1a; 静态广播接收者&#xff1a;通过 AndroidManifest.xm…...

redisson 使用fastJson2序列化

前因&#xff1a;一个项目&#xff1a;有人用redisTemplete存数据&#xff08;使用了fastjson2&#xff09;&#xff0c;使用redisson取的时候就会报错。要让redisTemplete与redisson序列化一致 一、自定义序列化器 import com.alibaba.fastjson2.JSON; import com.alibaba.fa…...

Python数据分析常用函数

Python基础 数字处理函数 Python提供了用于数字处理的内置函数和内置模块(math)&#xff0c;使用内置模块&#xff0c;需要先导入 import math。 内置函数math模块abs(-5)返回绝对值math.ceil(2.3)返回不小于x的最小整数divmod(9,4)返回商和余数math.floor(2.3)返回不大于x的…...

C++ 数据结构算法 学习笔记(32) -五大排序算法

C 数据结构算法 学习笔记(32) -五大排序算法 选择算法 如下若有多个女生的身高需要做排序: 常规思维: 第一步先找出所有候选美女中身高最高的&#xff0c;与最后一个数交换 第二步再找出除最后一位美女外其它美女中的最高者&#xff0c;与倒数第二个美女交换位置 再找出除最…...

从入门到精通:详解Linux进程管理

前言 在这篇文章中&#xff0c;我将带领大家深入学习和理解Linux系统中的进程管理。无论你是初学者还是有一定经验的开发者&#xff0c;相信这篇文章都会对你有所帮助。我们将详细讲解冯诺依曼体系结构、操作系统概念、进程管理、进程调度、进程状态、环境变量、内存管理以及其…...

【Linux】如何在 Linux 系统中使用 envsubst 来处理 Nginx 配置模板

一、创建 nginx.template 模板文件 vim nginx.template复制下面文件内容 server { listen ${BY_PORT}; server_name ${BY_HOST}; location /sys/ { proxy_pass http://${BY_GRAFANA_HOST}:${BY_GRAFANA_PORT}/; } # 其他配置... }这个模板中包含了几个环境变量&#…...

【LeetCode】438.找到字符串中所有字母异位词

找到字符串中所有字母异位词 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示…...

力扣96. 不同的二叉搜索树

Problem: 96. 不同的二叉搜索树 文章目录 题目描述思路复杂度Code 题目描述 思路 一个数字做根节点的话可能的结果为&#xff1a;其左边数字做子树的组合数字乘以其右边数字做子树的个数之积 1.创建备忘录memo&#xff1b; 2.递归分别求取当前数字左边和右边数字做子树的数量&…...

哈希表的用途

...