当前位置: 首页 > news >正文

对 async/await 的理解

async/await 的理解

async/await 其实是 Generator 的语法糖,它能实现的效果都能用then 链来实现,它是为优化 then 链而开发出来的。从字面上来看,async 是“异步”的简写,await 则为等待,所以很好理解async用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。当然语法上强制规定 await 只能出现在asnyc 函数中,先来看看 async 函数返回了什么:

async function testAsy() {return "hello world;";
}
let result = testAsy();
console.log(result);
Promise {<fulfilled>: 'hello world;'}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "hello world;"

所以,async 函数返回的是一个 Promise 对象。async 函数(包含函数语句、函数表达式、Lambda 表达式)会返回一个Promise对象,如果在函数中 return 一个直接量,async 会把这个直接量通过Promise.resolve() 封装成 Promise 对象。async 函数返回的是一个 Promise 对象,所以在最外层不能用await 获取其返回值的情况下,当然应该用原来的方式:then()链来处理这个 Promise 对象,就像这样:

async function testAsy() {return "hello world;";
}
let result = testAsy();
console.log(result);
result.then(res => {console.log(res); // hello world;
})

那如果 async 函数没有返回值,又该如何?很容易想到,他会返回

Promise.resolve(undefined);

联想一下 Promise 的特点——无等待,所以在没有await 的情况下执行 async 函数,它会立即执行,返回一个Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回Promise 对象的函数并无二致。

 注意:Promise.resolve(x) 可以看作是new Promise(resolve=>resolve(x)) 的简写可以用于快速封装字面量对象或其他对象,将其封装成 Promise 实例。

async/await 的优势

单一的 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了(很有意思,Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它)。
假设一个业务,分多个步骤完成,每个步骤都是异步的,而且依赖于上一个步骤的结果。仍然用 setTimeout 来模拟异步操作:

function takeLongTime(n) {return new Promise(resolve => {setTimeout(() => resolve(n + 200), n)})
};function step1(n) {console.log(`step1 with ${n}`);return takeLongTime(n);
}
function step2(n) {console.log(`step2 with ${n}`);return takeLongTime(n);
}
function step3(n) {console.log(`step3 with ${n}`);return takeLongTime(n);
}

现在用 Promise 方式来实现这三个步骤的处理:

function doIt(n) {console.time('doIt');const time1 = 300;step1(time1).then(time2 => step2(time2)).then(time3 => step3(time3)).then(result => {console.log(`result is ${result}`);console.timeEnd('doIt');});	
}doIt();
step1 with 300
step2 with 500
step3 with 700
result is 900
doIt: 1.652s

输出结果 result 是 step3() 的参数 700 + 200 = 900。doIt()顺序执行了三个步骤,一共用了 300 + 500 + 700 = 1500 毫秒,和console.time()/console.timeEnd() 计算的结果一致。如果用 async/await 来实现呢,会是这样:

async function doIt() {console.time('doIt');const time1 = 300;const time2 = await step1(time1);const time3 = await step2(time2);const result = await step3(time3);console.log(`result is ${result}`);console.timeEnd('doIt');
}
doIt();
step1 with 300
step2 with 500
step3 with 700
result is 900
doIt: 1.515s

结果和之前的 Promise 实现是一样的,但是这个代码看起来是不是清晰得多,几乎跟同步代码一样

async/await 对比 Promise 的优势

代码读起来更加同步,Promise 虽然摆脱了回调地狱,但是then的链式调⽤也会带来额外的阅读负担

Promise 传递中间值⾮常麻烦,⽽async/await⼏乎是同步的写法,⾮常优雅

错误处理友好,async/await 可以⽤成熟的try/catch,Promise的错误捕获⾮常冗余

调试友好,Promise 的调试很差,由于没有代码块,你不能在⼀个返回表达式的箭头函数中设置断点,如果你在⼀个.then 代码块中使⽤调试器的步进(step-over)功能,调试器并不会进⼊后续的.then代码块,因为调试器只能跟踪同步代码的每⼀步。

相关文章:

对 async/await 的理解

async/await 的理解 async/await 其实是 Generator 的语法糖&#xff0c;它能实现的效果都能用then 链来实现&#xff0c;它是为优化 then 链而开发出来的。从字面上来看&#xff0c;async 是“异步”的简写&#xff0c;await 则为等待&#xff0c;所以很好理解async用于申明一…...

Vue 整合 Element UI 、路由嵌套、参数传递、重定向、404和路由钩子(五)

一、整合 Element UI 1.1 工程初始化 使用管理员的模式进入 cmd 的命令行模式&#xff0c;创建一个名为 hello-vue 的工程&#xff0c;命令为&#xff1a; # 1、目录切换 cd F:\idea_home\vue# 2、项目的初始化&#xff0c;记得一路的 no vue init webpack hello-vue 1.2 安装…...

修改 Ubuntu 系统的时区

修改 Ubuntu 系统的时区 如果 Ubuntu 系统的时区设置不正确&#xff0c;您可以按照以下步骤进行调整&#xff1a; 1. 查看当前的时区设置&#xff0c;可以使用以下命令&#xff1a; timedatectl 这将显示当前系统的日期、时间和时区信息。 2. 如果时区设置不正…...

如何离线安装ModHeader - Modify HTTP headers Chrome插件?

如何离线安装ModHeader - Modify HTTP headers Chrome插件&#xff1f; 1.1 前言1.2 打开Chrome浏览器的开发者模式1.3 下载并解压打包好的插件1.4 解压下载好的压缩包1.5 加载插件1.6 如何使用插件? 1.1 前言 ModHeader 是一个非常好用的Chrome浏览器插件&#xff0c;可以用…...

在Linux中安装MySQL

在Linux中安装MySQL 检测当前系统中是否安装MySQL数据库 命令作用rpm -qa查询当前系统中安装的所有软件rpm -qa|grep mysql查询当前系统中安装的名称带mysql的软件rpm -qa | grep mariadb查询当前系统中安装的名称带mariadb的软件 RPM ( Red-Hat Package Manager )RPM软件包管理…...

python --windows获取启动文件夹路径/获取当前用户名/添加自启动文件

如何使用Python获取计算机用户名 一、Python自带的getpass模块可以用于获取用户输入的密码&#xff0c;但是它同样可以用来获取计算机用户名。 import getpassuser getpass.getuser() print("计算机用户名为&#xff1a;", user)二、使用os模块获取用户名 Python的…...

微信云托管(本地调试)⑥:nginx、vue刷新404问题

一、nginx默认路径 1.1、默认配置文件路径&#xff1a;/etc/nginx/nginx.conf 1.2、默认资源路径&#xff1a;/usr/share/nginx/html/index.html 二、修改nginx.conf配置 &#xff08;注意配置中的&#xff1a;include /etc/nginx/conf.d/*.conf; 里面包了一个server配置文件…...

数据结构 二叉树(一篇基本掌握)

绪论 雄关漫道真如铁&#xff0c;而今迈步从头越。 本章将开始学习二叉树&#xff08;全文共一万两千字&#xff09;&#xff0c;二叉树相较于前面的数据结构来说难度会有许多的攀升&#xff0c;但只要跟着本篇博客深入的学习也可以基本的掌握基础二叉树。 话不多说安全带系好&…...

​可视化绘图技巧100篇高级篇(四)-南丁格尔玫瑰图(二)

目录 前言 适用场景 不适用场景 ​堆积式南丁格尔玫瑰图( Nightingale Rose Diagram)...

Stable Diffusion - Candy Land (糖果世界) LoRA 提示词配置与效果展示

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132145248 糖果世界 (Candy Land) 是一个充满甜蜜和奇幻的地方&#xff0c;由各种各样的糖果和巧克力构成。在糖果世界&#xff0c;可以看到&…...

ES6学习-module语法

Module语法 CommonJS模块 let { readfile } require(fs) # 等同于 let _fs require(fs) let readfile _fs.readfile //这种加载称为“运行时加载”ES6模块 import { stat, exists, readFile } from fs;这种加载称为“编译时加载”或者静态加载 静态加载带来的各种好处 …...

Flutter 实现按位置大小比例布局的控件

文章目录 前言一、如何实现&#xff1f;1、数值转成分数2、RowFlexible布局横向3、ColumnFlexible布局纵向 二、完整代码三、使用示例1、基本用法2、四分屏3、六分屏4、八分屏5、九分屏6、414分屏 总结 前言 做视频监控项目时需要需要展示多分屏&#xff0c;比如2x2、3x3、414…...

ES6 - 对象新增的一些常用方法

文章目录 1&#xff0c;Object.is()2&#xff0c;Object.asign()3&#xff0c;Object.getOwnPropertyDescriptors()4&#xff0c;Object.setPrototypeOf()和getPrototypeOf()5&#xff0c;Object.keys()、values() 和 entries()6&#xff0c;Object.fromEntries()7&#xff0c;…...

半导体存储电路

存储电路 存储单元&#xff1a;只能存储一位数据 寄存器&#xff1a;存储一组数据 存储单元 静态存储单元&#xff1a;包含锁存器和触发器&#xff0c;只要不断电&#xff0c;静态存储单元的状态会一直保持下去。 动态存储单元&#xff1a;利用电容的电荷存储效应来存储数据。…...

web前端之CSS操作

文章目录 一、CSS操作1.1 html元素的style属性1.2 元素节点的style属性1.3 cssText属性 二、事件2.1 事件处理程序2.1.1 html事件2.1.2 DOM0事件&#xff08;适合单个事件&#xff09;2.1.3 DOM2事件&#xff08;适合多个事件&#xff09; 2.2 事件之鼠标事件2.3 事件之Event事…...

Python SQLAlchemy ( ORM )

From Python中强大的通用ORM框架&#xff1a;SQLAlchemy&#xff1a;https://zhuanlan.zhihu.com/p/444930067Python ORM之SQLAlchemy全面指南&#xff1a;https://zhuanlan.zhihu.com/p/387078089 SQLAlchemy 文档&#xff1a;https://www.sqlalchemy.org/ SQLAlchemy入门和…...

鉴源实验室丨汽车网络安全运营

作者 | 苏少博 上海控安可信软件创新研究院汽车网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 概 述 1.1 背景 随着车辆技术的不断进步和智能化水平的提升&#xff0c;车辆行业正经历着快速的变革和技术进步。智能化…...

分布式链路追踪之SkyWalking详解和实战

SkyWalking 文章目录 SkyWalking1.SkyWalking概述2.SkyWalking架构设计3.SkyWalking部署4.应用程序接入SkyWalking5.SkyWalking配置应用告警5.1.告警规则5.2.Webhook&#xff08;网络钩子&#xff09;5.3.邮件告警实践 6.项目自动化部署接入SkyWalking6.1 整体思路6.2 启动参数…...

【工程实践】使用EDA(Easy Data Augmentation)做数据增强

工程项目中&#xff0c;由于数据量不够&#xff0c;经常需要用到数据增强技术&#xff0c;尝试使用EDA进行数据增强。 1.EDA简介 EDA是一种简单但是非常有效的文本数据增强方法&#xff0c;是由美国Protago实验室发表于 EMNLP-IJCNLP 2019 会议。EDA来自论文《EDA: Easy Data…...

ClickHouse(十三):Clickhouse MergeTree系列表引擎 - ReplicingMergeTree

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...