js异步之宏任务(marcroTask)和微任务(microTask)

2024-02-15 20:30

本文主要是介绍js异步之宏任务(marcroTask)和微任务(microTask),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先看一到面试题

写出console.log的输出顺序

console.log(100);setTimeout(()=>{console.log(200);
})setTimeout(()=>{console.log(201);
})Promise.resolve().then(()=>{console.log(300);
})console.log(400);// 100 400 300 200 201
// 为什么300比200先打印

为什么300比200先打印这里就引出了宏任务和微任务????

什么是宏任务和微任务


在这里插入图片描述

宏任务包括:setTimeout setInterval Ajax DOM事件
微任务:Promise async/await
微任务比宏任务的执行时间要早

异步和单线程


异步和单线程是相辅相成的,js是一门单线程脚本语言,所以需要异步来辅助

异步和同步的区别:

  • 异步不会阻塞程序的执行,
  • 同步会阻塞程序的执行,

前端使用异步的场景:

  1. 定时任务:setTimeout,setInverval
  2. 网络请求:ajax请求,动态<img>加载
  3. 事件绑定
//ajax请求代码示例
console.log('start')
$.get('./data1.json',function(data1){console.log(data1)
})
console.log('end')

加载示例:
在这里插入图片描述
事件绑定示例:
在这里插入图片描述

也就是请求处理过程中,你不能闲着,会产生异步的请求,回头再处理,然后继续执行下面的请求。

同步阻塞示例:

console.log(1000)
alert(200)
console.log(3000)

上面就是同步阻塞示例,你不点击alert确认窗口,不会打印3000

js绝大部分都是同步,不过多详解;

同步异步问题


首先,你要知道javascript是单线程语言。js任务需要排队顺序执行,如果一个任务耗时过长,后边一个任务也的等着,但是,假如我们需要浏览新闻,但新闻包含的超清图片加载很慢,总不能网页一直卡着直到图片完全出来,所以将任务设计成了两类:

同步任务
异步任务

当我们打开网站时,网页的渲染过程就是一大堆同步任务,像页面骨架和页面元素的渲染,而加载图片、音乐之类的任务就是异步任务,看一下下边导图:

在这里插入图片描述
同步和异步任务分别进入不同的执行“场所”,同步进入主线程,异步进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入任务队列(Event Queue)。主线程内的任务执行完毕为空,就去任务队列(Event Queue)读取对应的函数,进入主线程执行。

上述过程会不断重复,也就是常说的Event Loop(事件循环)。

但是,JS异步还有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入任务队列(event queue),然后再执行微任务,将微任务放入微任务队列(micro task queue),但是,这两个queue不是一个queue。当你往外拿的时候先从微任务队列里拿这个回调函数,然后再从宏任务的queue拿宏任务的回调函数,如下图:

在这里插入图片描述
在这里插入图片描述

任务列队和event loop(事件循环)

单线程就意味着,所有的任务都要排队,前一个结束,才会执行后面的任务。如果列队是因为计算量大,CPU忙不过来,倒也算了。但是更多的时候,CPU是闲置的,因为IO设备处理得很慢,例如
ajax读取网络数据。js设计者便想到,主线程完全可以不管IO设备,将其挂起,然后执行后面的任务。等后面的任务结束掉,在反过头来处理挂起的任务。

好,我们来梳理一下:

1)所有的同步任务都在主线程上执行,行成一个执行栈。

2)除了主线程之外,还存在一个任务列队,只要异步任务有了运行结果,就在任务列队中植入一个时间标记。

3)主线程完成所有任务(执行栈清空),就会读取任务列队,先执行微任务队列在执行宏任务队列。

4)重复上面三步。

只要主线程空了,就会读取任务列队,这就是js的运行机制,也被称为 event loop(事件循环)

三、执行顺序


1.主线程上宏任务、微任务执行顺序

console.log('---start---');//第一轮主线程setTimeout(() => {console.log('setTimeout');  // 将回调代码放入个宏任务队列,第二轮宏任务执行
}, 0);new Promise((resolve, reject) => {console.log('---Promise第一轮微任务同步执行---');//第一轮微任务同步执行resolve()
}).then(()=>{console.log('Promise.then实例成功回调执行'); // 将回调代码放入微任务队列,第一轮宏任务执行完后立即执行
});console.log('---end---');//第一轮主线程结束

在这里插入图片描述

执行顺序:主线程 >> 主线程上创建的微任务 >> 主线程上创建的宏任务

2.宏任务中包含微任务

// 宏任务队列 1
setTimeout(() => {// 宏任务队列 2.1console.log('timer_1');setTimeout(() => {// 宏任务队列 3console.log('timer_3')}, 0)new Promise(resolve => {resolve()console.log('new promise')}).then(() => {// 微任务队列 1console.log('promise then')})
}, 0)setTimeout(() => {// 宏任务队列 2.2console.log('timer_2')
}, 0)
console.log('========== Sync queue ==========')

执行顺序:主线程 >> 主线程上的宏任务队列1 >> 宏任务队列1中创建的微任务

========== Sync queue ==========1 timer_1
2 new promise
3 promise then
4 timer_2
5 timer_3

//请写出输出内容async function async1() {console.log('async1 start');await async2();console.log('async1 end');}async function async2() {console.log('async2');}console.log('script start');setTimeout(function() {console.log('setTimeout');}, 0)async1();new Promise(function(resolve) {console.log('promise1');resolve();}).then(function() {console.log('promise2');});console.log('script end');

这篇关于js异步之宏任务(marcroTask)和微任务(microTask)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Spring定时任务只执行一次的原因分析与解决方案

《Spring定时任务只执行一次的原因分析与解决方案》在使用Spring的@Scheduled定时任务时,你是否遇到过任务只执行一次,后续不再触发的情况?这种情况可能由多种原因导致,如未启用调度、线程... 目录1. 问题背景2. Spring定时任务的基本用法3. 为什么定时任务只执行一次?3.1 未启用