事件队列事件循环(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

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

一些其他面试题

阿里二面:那你来说说定时任务?单机、分布式、调度框架下的定时任务实现是怎么完成的?懵了。。_哔哩哔哩_bilibili 1.定时算法 累加,第二层每一个格子是第一层的总时间400 ms= 20 * 20ms 2.MQ消息丢失 阿里二面:高并发场景下引进消息队列有什么问题?如何保证消息只被消费一次?真是捏了一把汗。。_哔哩哔哩_bilibili 发送消息失败

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor