async/await代码执行顺序分析及宏任务和微任务简介

2024-02-15 20:30

本文主要是介绍async/await代码执行顺序分析及宏任务和微任务简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、async

带async关键字的函数,是声明异步函数,返回值是promise对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装。

 

返回值为 Promise {<resolved>: "test"}。

 

二、await

await等待右侧表达式的结果,这个结果是promise对象或者其他值。

如果它等到的不是一个 promise 对象,那 await 表达式的运算结果就是它等到的东西。

如果它等到的是一个 promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

 

由于test()造成的阻塞,console.log('end')会等到两秒后执行

所以为了避免造成阻塞,await 必须用在 async 函数中,async 函数调用不会造成阻塞。

 

先执行console.log('end'),两秒后执行console.log('test')

如果await用在普通函数中,会报错,如下:

 

三、async/await的执行顺序

遇到await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码。(好好理解一下上面的说明。也就是说,await只会阻塞当前async方法内的代码,不会影响外部代码的执行)

以下面的代码分析:

 

执行的结果:

 

· 首先执行宏任务,执行test1函数,执行console.log('statr test1')

· 遇到await,先执行右边test2中的console.log('test2'),中断了后面的代码,执行test1外面的同步代码

· 执行console.log('start async');

· 遇到setTimeout,推到到下个宏任务队列中

· 执行Promise里面的同步代码console.log('promise1')

· 运行到promise().then,发现是promise对象,推到微任务队列中

· 执行console.log('end async')

· test1外面的同步代码执行结束后,回到test1中,console.log(await test2())执行完成后返回Promise {<resolved>: "return test2 value"},是promise对象,推到微任务队列中

· 此时第一个宏任务结束,执行所有的微任务,因为微任务队列先进先出,所以先执行console.log('promise2'),后执行console.log('return test2 value')

· 执行test2完成后,后面的代码不再阻塞,执行console.log('end test1');

· 执行下个宏任务,即执行console.log('setTimeout');

补充下有关宏任务和微任务的知识

宏任务和微任务都是队列,宏任务有script、setTimeout、setInterval等,微任务有Promise.then catch finally、process.nextTick等,宏任务和微任务的关系如下:

 

先执行第一个宏任务,执行结束后,执行所有的微任务,然后执行下个宏任务。

四、async/await的优缺点

1. 优点

相对于promise,async/await处理 then 的调用链,代码要清晰很多,几乎和同步代码一样

2. 缺点

滥用 await 可能会导致性能问题,因为 await 会阻塞代码

五、处理reject

1. try/catch

2. catch

参考:

1. https://segmentfault.com/a/1190000007535316

2. https://segmentfault.com/a/1190000017224799

3. https://www.cnblogs.com/wangziye/p/9566454.html

 

这篇关于async/await代码执行顺序分析及宏任务和微任务简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

一文详解Java Condition的await和signal等待通知机制

《一文详解JavaCondition的await和signal等待通知机制》这篇文章主要为大家详细介绍了JavaCondition的await和signal等待通知机制的相关知识,文中的示例代码讲... 目录1. Condition的核心方法2. 使用场景与优势3. 使用流程与规范基本模板生产者-消费者示例

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制