事件队列事件循环(EventLoop) 宏任务 微任务详解 面试题

2024-04-03 21:12

本文主要是介绍事件队列事件循环(EventLoop) 宏任务 微任务详解 面试题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事件队列 事件循环 EventLoop 宏任务 微任务详解

  • 一、概念
  • 二、宏任务(多个)、微任务(1个)
  • 三、Promise 的构造函数
  • 四、process.nextTick在事件循环中的处理
  • 五、vue nextTick原理

一、概念

event: 事件
loop: 循环,循环的是一个又一个的任务队列
任务队列: 是一个先进先出的数据结构, 排在前面的事件, 优先被主进程读取
任务队列分为: 宏队列, 微队列, 分别存放在宏任务和微任务

ES6 规范中,microtask 称为 jobs,macrotask 称为 task,宏任务是由宿主发起的,而微任务由JavaScript自身发起。

二、宏任务(多个)、微任务(1个)

我们常见的点击和键盘等事件也宏任务

  1. 常见的宏任务
  • setTimeout()
  • setInterval()
  • setImmediate()
  • script
  1. 常见的微任务
  • promise.then()
  • promise.catch()
  • new MutaionObserver()
  • process.nextTick()
  1. 本质区别
    宏任务特征: 有明确的异步任务需要执行和回调; 需要其他异步线程支持。
    微任务特征: 没有明确的异步任务需要执行,只有回调;不需要其他异步线程支持。

  2. 执行顺序(这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop 事件循环)
    console.log = promise -> promise.nextTick -> promise.then -> setTimeout -> setImmediate
    ①先按代码顺序将同步任务压入主执行栈中执行
    ②遇到异步任务则先将异步任务压入对应的任务队列中(宏队列或微队列)
    ③同步任务执行完毕后,查看微队列,将微任务一一取出进入主执行栈中执行
    ④微任务队列清空后,再查看宏队列,只取出第一个宏任务执行,执行完

  • 首先我们分析有多少个宏任务;
  • 在每个宏任务中,分析有多少个微任务;
  • 根据调用次序,确定宏任务中的微任务执行次序;
  • 确定整个顺序。
    then中的回调函数要确定Promise状态后才能压入微队列

Event Loop 在压入事件时,都会判断微任务队列是否还有需要执行的事件:如果有,则优先将需要执行的微任务压入;没有,则依次压入需要执行宏任务!
事件循环 宏任务 微任务 示意图
事件循环 宏任务 微任务 示意图

//  Promise 中的执行顺序
const promise = new Promise(function(resolve, reject) {console.log('Promise');resolve();
});promise.then(() => {console.log('resolved');
});console.log('Hi!'); // Promise Hi!resolved
// 执行顺序
setTimeout(function () {console.log(1);
});new Promise(function (resolve,reject) {console.log(2);resolve(3);
}).then(function (val) {console.log(val);new Promise((resolve,reject) => {console.log(5);resolve(7);}).then(function (val) {console.log(val);});
});
console.log(4);// 先按顺序执行同步任务
// Promise 新建后立即执行输出2, 接着输出4, 异步任务等同步任务执行完成后执行
// 且同一次事件循环中, 微任务永远在宏任务之前执行。这时候执行栈空了,执行事件队列,
// 先取出微任务, 输出3, 最后取出宏任务, 输出1

三、Promise 的构造函数

Promise 构造函数是 JavaScript 中用于创建 Promise 对象的内置构造函数。
Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。
起始函数执行成功时,它应该调用 resolve 函数并传递成功的结果。当起始函数执行失败时,它应该调用 reject 函数并传递失败的原因。
Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:
then:用于处理 Promise 成功状态的回调函数。
catch:用于处理 Promise 失败状态的回调函数。
finally:无论 Promise 是成功还是失败,都会执行的回调函数。
当 Promise 被构造时,起始函数会被同步执行;

四、process.nextTick在事件循环中的处理

process.nextTick是Node环境的变量,process.nextTick() 是一个特殊的异步API,其不属于任何的Event Loop阶段。事实上Node在遇到这个API时,Event Loop根本就不会继续进行,会马上停下来执行process.nextTick(),这个执行完后才会继续Event Loop。所以,nextTick和Promise同时出现时,肯定是process.nextTick() 先执行。

可以类比 Vue.$nextTick(),也是需要执行完这个函数后,才能继续Event Loop。

五、vue nextTick原理

Vue.nextTick() 是一个方法,用于在下次 DOM 更新循环结束之后执行延迟回调。它的实现原理是利用浏览器的异步任务队列机制,在 tick 时刻将回调函数放入队列中等待执行。在实现上,nextTick 方法会根据当前环境选择不同的底层实现。在现代浏览器中,它使用了 MutationObserver 和 Promise 等技术实现异步任务调度;在旧版浏览器中,则使用了 setTimeout 来模拟异步任务。

Vue.nextTick()的实现原理主要是将回调函数推入到一个队列中,在下一个事件循环周期(MacroTask)中执行这个队列中的所有回调函数。具体来说,当用户使用 Vue.nextTick()执行回调函数时,Vue.js 会按照以下步骤进行处理:

1.首先,Vue.js 会将回调函数推入到一个队列中。这个队列称为“异步更新队列”(Async Queue),它是 Vue.js 用于收集在同一事件循环周期内需要执行的所有异步任务的容器。
2.接着,Vue.js 会判断当前是否存在一个微任务(MicroTask)队列。如果存在,则将异步更新队列合并到微任务队列中;否则,创建一个新的微任务队列,并将异步更新队列添加到其中。
3.接着,Vue.js 会将当前执行上下文捕获并保存下来。这个上下文包含了当前执行 Vue.nextTick()方法的组件实例、数据变化等信息。
4.最后,Vue.js 会将一个微任务添加到微任务队列中。这个微任务的作用是在下一个事件循环周期中执行异步更新队列中的所有回调函数,并且在执行之前恢复上下文,确保回调函数能够正确地访问到相关数据。

// 下面是一个简单的示例代码,演示了 Vue.nextTick()的使用方法和实现原理:
// 定义一个 Vue 实例
var vm = new Vue({el: '#app',data: {message: 'Hello, world!',},
});// 在数据更新后执行回调函数
vm.message = 'Hello, Vue.js!';
Vue.nextTick(function () {console.log('DOM updated!');
});
// 输出:'DOM updated!'

在这个示例中,我们首先定义了一个 Vue 实例,并通过数据绑定将 message 属性绑定到了页面上。然后,我们通过修改 message 属性的值来触发视图更新,并在 Vue.nextTick()方法中添加了一个回调函数来检查 DOM 是否已经更新。

当我们运行这段代码时,Vue.js 会按照上述步骤进行处理,并在下一个事件循环周期中执行回调函数。因此,我们可以在控制台中看到输出结果。

总的来说,Vue.nextTick()提供了一种非常方便的方式来处理 DOM 更新后的回调函数,可以帮助我们避免一些常见的问题,例如在获取 DOM 元素的位置或尺寸时可能会遇到的延迟问题。同时,它的实现也为我们提供了一种思路,

与 node 的 nextTick 的区别
Vue.nextTick和 Node.js 的process.nextTick虽然名字相似,但是它们的功能和用途不同。

Vue.nextTick是 Vue.js 提供的一个方法,主要用于在 DOM 更新之后执行某些操作,例如更新完数据后获取更新后的 DOM 节点。它利用了浏览器的异步渲染机制,将回调函数推迟到下一个 DOM 更新周期中执行。

process.nextTick是 Node.js 提供的一个方法,主要用于在当前事件循环的末尾、下一次事件循环之前执行一些操作。它可以让你在当前事件循环中的所有 I/O 操作完成后立即执行回调函数,而不必等待下一次事件循环。

因此,Vue.nextTick和process.nextTick虽然名称相似,但是它们的作用和使用场景不同,不能互相替代。

这篇关于事件队列事件循环(EventLoop) 宏任务 微任务详解 面试题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/873994

相关文章

详解MySQL中DISTINCT去重的核心注意事项

《详解MySQL中DISTINCT去重的核心注意事项》为了实现查询不重复的数据,MySQL提供了DISTINCT关键字,它的主要作用就是对数据表中一个或多个字段重复的数据进行过滤,只返回其中的一条数据... 目录DISTINCT 六大注意事项1. 作用范围:所有 SELECT 字段2. NULL 值的特殊处

SQL BETWEEN 语句的基本用法详解

《SQLBETWEEN语句的基本用法详解》SQLBETWEEN语句是一个用于在SQL查询中指定查询条件的重要工具,它允许用户指定一个范围,用于筛选符合特定条件的记录,本文将详细介绍BETWEEN语... 目录概述BETWEEN 语句的基本用法BETWEEN 语句的示例示例 1:查询年龄在 20 到 30 岁

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

HTML5 搜索框Search Box详解

《HTML5搜索框SearchBox详解》HTML5的搜索框是一个强大的工具,能够有效提升用户体验,通过结合自动补全功能和适当的样式,可以创建出既美观又实用的搜索界面,这篇文章给大家介绍HTML5... html5 搜索框(Search Box)详解搜索框是一个用于输入查询内容的控件,通常用于网站或应用程

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可