浏览器事件循环机制、宏任务和微任务

news2024/12/25 2:36:20

浏览器的事件循环机制(重要)

图片

image-20230608154453933

执行顺序如下:

  • 同步任务:进入主线程后,立即执行。

  • 异步任务:会先进入 Event Table;等时间到了之后,再进入 任务队列 (Event Queue)排队(排队是因为同一时间,JS 只能执行一个任务),先进先出。比如说,setTimeout(()=> {}, 1000)这种定时器任务,需要等一秒之后再进入 Event Queue。

  • 当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。

Node.js 事件循环机制

浏览器的 EventLoop 依据的是 HTML5 规范。而 Node.js 的 EventLoop 是由Node.js底层的 libuv 规定的。 libuv是一个专注于异步IO的跨平台库。

Node.js的事件循环中,有六个队列。其中,微任务有两个队列,宏任务有四个队列。

一、微任务队列:

  • 顺序1:next tick queue。比如:process.nextTick

  • 顺序2:other queue。比如:Promise的then回调、queueMicrotask

二、宏任务队列:

  • 顺序3:timer queue。比如:setTimeout、setInterval

  • 顺序4:poll queue。比如:IO事件

  • 顺序5:check queue。比如:setImmediate

  • 顺序6:close queue。比如:close事件

参考链接:

  • 【荐】浏览器及nodeJS中的EventLoop事件循环机制:https://www.cnblogs.com/weiyongchao/p/13766429.html

  • 浏览器和Node 事件循环的区别:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/26

宏任务和微任务

JS中的任务分为同步任务、异步任务。

JS中的异步任务分为宏任务(macrotask)、微任务(microtask)。在早期,异步任务中只有宏任务,没有微任务。后来的语言标准中,推出了“微任务”,因为希望微任务能够尽早执行

宏任务、微任务分类

事件循环的队列中,有两个队列。

1、宏任务队列,包含这些任务:

  • ajax 网络请求

  • setTimeout、setInterval

  • DOM事件

  • UI渲染

  • I/O文件读写操作。

2、微任务队列,包含这些任务:

  • Promise的then回调

  • Mutation Observer API:监听DOM节点变化。

  • queueMicrotask():可直接将某个任务加入到微任务队列中。

在执行一个 Promise 对象时,当走完 resolve() 进入 fulfilled状态后,会立刻把 .then()里面的代码加入到微任务队列当中。

任务的执行顺序

JS中的任务执行顺序:同步任务 --> 微任务 --> 宏任务

在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查询微任务队列中是否还有任务需要执行

  • 当前宏任务执行之前,必须要保证微任务队列是空的。

  • 如果微任务队列不为空,那就优先执行微任务队列中的任务。

任务执行顺序的面试题

实际开发中,基本不会出现下面这些题目,因为很多时候我们无法精准控制异步任务的执行顺序。但是它们在面试中出现的频率特别高,因为熟悉这些思维训练,有利于考察我们对JS单线程、事件循环机制、宏任务和微任务等原理的掌握程度。

题 1:宏任务和微任务的执行顺序

setTimeout(() => {
  // 宏任务
  console.log('setTimeout');
}, 0);
 
new Promise((resolve, reject) => {
  resolve();
  console.log('promise1'); // 同步任务
}).then((res) => {
  // 微任务
  console.log('promise then');
});
 
console.log('同步任务'); // 同步任务

打印结果:

promise1
同步任务
promise then
setTimeout

上方代码执行的顺序依次是:同步任务 --> 微任务 --> 宏任务

题 2:在宏任务中嵌套了微任务

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve();
    console.log('setTimeout'); // 宏任务
  }, 0);
  console.log('promise1');
}).then((res) => {
  // 微任务
  console.log('promise then');
});
 
console.log('同步任务');

打印结果:

promise1
同步任务
setTimeout
promise then

上方代码解释:在执行宏任务的过程中,创建了一个微任务。但是需要先把当前这个宏任务执行完,再去创建并执行微任务。

题3:综合题

console.log("script start")
 
setTimeout(() => {
  console.log("setTimeout1");
  new Promise(resolve => {
    resolve();
  }).then(() => {
    new Promise(resolve => {
      resolve();
    }).then(() => {
      console.log("then1");
    });
    console.log("then2");
  });
});
 
new Promise(resolve => {
  // 下面这两行代码,即便调换顺序,也不影响打印结果
  console.log("promise1");
  resolve();
}).then(() => {
  console.log("then3");
});
 
setTimeout(() => {
  console.log("setTimeout2");
});
 
console.log('同步代码');
 
queueMicrotask(() => {
  console.log("queueMicrotask")
});
 
new Promise(resolve => {
  resolve();
}).then(() => {
  console.log("then4");
});
 
console.log("script end");

打印结果:

// 第一次循环
script start
promise1
同步代码
script end
 
// 第二次循环
then3
queueMicrotask
then4
 
// 第三次循环
setTimeout1
then2
then1
 
// 第四次循环
setTimeout2

题4:async await 题目

代码举例:

console.log('script start')
 
async function async2() {
  console.log('async2')
}
 
async function async1() {
  console.log('async1 start')
  await async2();
  console.log('async1 end')
}
 
setTimeout(() => {
  console.log('setTimeout')
}, 0)
 
async1();
 
new Promise(resolve => {
  console.log('promise1')
  resolve();
}).then(function () {
  console.log('then1')
})
 
console.log('script end');

打印结果:

script start
async1 start
async2
promise1
script end
 
async1 end
then1
 
setTimeout

原文地址:浏览器事件循环机制、宏任务和微任务 

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

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

相关文章

探索 Spring 框架:企业级应用开发的强大工具

CSDN-个人主页:17_Kevin-CSDN博客 收录专栏:《Java》 目录 一、引言 二、Spring 框架的历史 三、Spring 框架的核心模块 四、Spring 框架的优势 五、Spring 框架的应用场景 六、结论 一、引言 在当今数字化时代,企业级应用开发的需求日…

腾讯春招后端一面(八股篇)

前言 前几天在网上发了腾讯面试官问的一些问题,好多小伙伴关注,今天对这些问题写个具体答案,博主好久没看八股了,正好复习一下。 面试手撕了三道算法,这部分之后更,喜欢的小伙伴可以留意一下我的账号。 1…

【刷题训练】LeetCode125. 验证回文串

验证回文串 题目要求 示例 1: 输入: s “A man, a plan, a canal: Panama” 输出:true 解释:“amanaplanacanalpanama” 是回文串。 示例 2: 输入:s “race a car” 输出:false 解释:“rac…

elasticsearch8.12 分词器安装

分词器的主要作用将用户输入的一段文本,按照一定逻辑,分析成多个词语的一种工具 分词器下载地址 analysis-ik Releases infinilabs/analysis-ik GitHub 一个简便 安装方式 安装完成之后 会提示重启,重启es即可 ./bin/elasticsearch-pl…

19C 19.22 RAC 2节点一键安装演示

Oracle 一键安装脚本,演示 2 节点 RAC 一键安装过程(全程无需人工干预):(脚本包括 GRID/ORALCE PSU/OJVM 补丁自动安装) ⭐️ 脚本下载地址:Shell脚本安装Oracle数据库 脚本第三代支持 N 节点…

Excel小技巧 (3) - 如何取整

1. 四舍五入 Round(对象,小数点后位数) 结果 123.1 2.向上取整 Roundup(对象,小数点后位数) 结果:123.2 3.向下取整 Round(对象,小数点后位数) 结果123.…

每日一题 2312卖木头快

2312. 卖木头块 题目描述: 给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices ,其中 prices[i] [hi, wi, pricei] 表示你可以以 pricei 元的价格卖一块高为 hi 宽为 wi 的矩形木块。 每一次操作中&am…

AJAX 05 axios拦截器、数据管理平台

AJAX 学习 AJAX 05 黑马头条-数据管理平台项目准备业务1:验证码登录bootstrap提示框实际业务中的验证码登录token 【注】HTML遗落的知识【注】JS遗漏的知识业务2:个人信息设置 & axios拦截器axios请求拦截器axios响应拦截器 业务3:发布文…

网络架构层_服务器上下行宽带

网络架构层_服务器上下行宽带 解释一 云服务器ECS网络带宽的概念、计费、安全及使用限制_云服务器 ECS(ECS)-阿里云帮助中心 网络带宽是指在单位时间(一般指的是1秒钟)内能传输的数据量,带宽数值越大表示传输能力越强,即在单位…

mysql 主从延迟分析

一、如何分析主从延迟 分析主从延迟一般会采集以下三类信息。 从库服务器的负载情况 为什么要首先查看服务器的负载情况呢?因为软件层面的所有操作都需要系统资源来支撑。 常见的系统资源有四类:CPU、内存、IO、网络。对于主从延迟,一般会…

提前十分钟!有方法论的人和没有方法论的人,谁更从容?弱者不应被错误引导——早读(逆天打工人爬取热门微信文章解读)

熬夜不熬夜,取决于你的生活态度 引言Python 代码第一篇 人民日报 提前十分钟,人生大不同第二篇 人民日报 来啦 新闻早班车要闻社会政策 结尾 君子如潜龙,藏器待时发 紧握时间的脉搏,提前规划十分钟 既显对他人的敬意,亦…

并发编程之创建线程的几种方式以及运行的详细解析

3.1 创建和运行线程 方法一,直接使用 Thread // 创建线程对象 Thread t new Thread() {public void run() {// 要执行的任务} }; // 启动线程 t.start(); 例如: // 构造方法的参数是给线程指定名字,推荐 Thread t1 new Thread("t1…

04- 基于SpringAMQP封装RabbitMQ,消息队列的Work模型和发布订阅模型

SpringAMQP 概述 使用RabbitMQ原生API在代码中设置连接MQ的参数比较繁琐,我们更希望把连接参数写在yml文件中来简化开发 SpringAMQP是基于AMQP协议定义的一套API规范,将RabbitMQ封装成一套模板用来发送和接收消息 AMQP(Advanced Message Queuing Portocol)是用于在应用程序…

go语言基础笔记

1.基本类型 1.1. 基本类型 bool int: int8, int16, int32(rune), int64 uint: uint8(byte), uint16, uint32, uint64 float32, float64 string 复数:complex64, complex128 复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部…

某赛通电子文档安全管理系统 DecryptApplication 任意文件读取漏洞(2024年3月发布)

漏洞简介 某赛通电子文档安全管理系统 DecryptApplication 接口处任意文件读取漏洞,未经身份验证的攻击者利用此漏洞获取系统内部敏感文件信息,导致系统处于极不安全的状态。 漏洞等级高危影响版本*漏洞类型任意文件读取影响范围>1W 产品简介 …

案例分析篇06:数据库设计相关28个考点(17~22)(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

Jmeter入参问题小记

表单入参的时候,这个地方需要勾选,如果不☑️选的话,会提示errorMsg":"Required String parameter code is not present",

Leet code 三步问题

解题思路:动态规划 先观察 1级台阶 1种方法 2级台阶 2种方法 3级台阶 4种方法 4级台阶 7种方法 5级台阶 13种方法 可以看出规律 从3级台阶后 每级台阶需要从前三层台阶和相加 注意:后面值会过大 需要在相加之后就模运算1000000007 代码如下 clas…

.NET高级面试指南专题十八【 外观模式模式介绍,提供了简化的接口,隐藏系统的复杂性】

介绍: 外观模式是一种结构设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。外观模式定义了一个高层接口,使得子系统更容易使用。 原理: 外观类(Facade Class):提供了一…

C++面试问题收集

0 持续更新中 目录 0 持续更新中 1 C语言相关 1.1 malloc/free和new/delete区别 1.2 内存泄漏 1.3 堆区和栈区的区别 1.4 宏定义和const的区别 1.5 多态 1.6 类中的静态成员变量 2 操作系统相关 2.1 进程和(用户)线程的区别 2.2 系统调用 2.3…