Promise、async、await 、异步生成器的错误处理方案

1、Promise.all 的错误处理

Promise.all 方法接受一个 Promise 数组,并返回所有解析 Promise 的结果数组:

const promise1 = Promise.resolve("one");
const promise2 = Promise.resolve("two");Promise.all([promise1, promise2]).then((results) => console.log(results));// 结果: ['one', 'two']

如果这些 Promise 中的任何一个被拒绝,Promise.all 将拒绝并返回第一个被拒绝的 Promise 的错误。

为了在 Promise.all 中处理这些情况,可以使用 catch:

const promise1 = Promise.resolve("good");
const promise2 = Promise.reject(Error("Bad"));
const promise3 = Promise.reject(Error("Bad+"));Promise.all([promise1, promise2, promise3]).then(results => console.log(results)).catch(error => console.error(error.message));

如果想要运行一个函数而不考虑 Promise.all 的结果,可以使用 finally:

Promise.all([promise1, promise2, promise3]).then(results => console.log(results)).catch(error => console.error(error.message)).finally(() => console.log("Finally"));

2、Promise.any 的错误处理

Promise.any 和 Promise.all 恰恰相反。Promise.all 如果某一个失败,就会抛出第一个失败的错误。而 Promise.any 总是返回第一个成功的 Promise,无论是否发生任何拒绝。

相反,如果传递给 Promise.any 的所有 Promise 都被拒绝,那产生的错误就是 AggregateError。 来看下面的例子:

const promise1 = Promise.reject(Error("Error"));
const promise2 = Promise.reject(Error("Error+"));Promise.any([promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error)).finally(() => console.log("Finally"));

输出结果如下:

fileOf7174.png

这里用 catch 处理错误。AggregateError 对象具有与基本错误相同的属性,外加一个 errors 属性:

const promise1 = Promise.reject(Error("Error"));
const promise2 = Promise.reject(Error("Error+"));Promise.any([promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error.errors)).finally(() => console.log("Finally"));

此属性是一个包含所有被拒绝的错误信息的数组:

fileOf7174.png

3、Promise.race 的错误处理

Promise.race 接受一个 Promise 数组,并返回第一个成功的 Promise 的结果:

const promise1 = Promise.resolve("one");
const promise2 = Promise.resolve("two");Promise.race([promise1, promise2]).then(result => console.log(result)
);// 结果:one

那如果有被拒绝的 Promise,但它不是传入数组中的第一个呢:

const promise1 = Promise.resolve("one");
const rejection = Promise.reject(Error("Bad"));
const promise2 = Promise.resolve("two");Promise.race([promise1, rejection, promise2]).then(result =>console.log(result)
);// 结果:one

这样结果还是 one,不会影响正常的执行。

如果被拒绝的 Promise 是数组的第一个元素,则 Promise.race 拒绝,就必须要必须捕获拒绝:

const promise1 = Promise.resolve("one");
const rejection = Promise.reject(Error("Bad"));
const promise2 = Promise.resolve("two");Promise.race([rejection, promise1, promise2]).then(result => console.log(result)).catch(error => console.error(error.message));// Bad

4、Promise.allSettled 的错误处理

Promise.allSettled 是 ECMAScript 2020 新增的 API。它和 Promise.all 类似,不过不会被短路,也就是说当 Promise 全部处理完成后,可以拿到每个 Promise 的状态, 而不管其是否处理成功。

来看下面的例子:

const promise1 = Promise.resolve("Good!");
const promise2 = Promise.reject(Error("Bad!"));Promise.allSettled([promise1, promise2]).then(results => console.log(results)).catch(error => console.error(error)).finally(() => console.log("Finally"));

这里向 Promise.allSettled 传递了一个包含两个 Promise 的数组:一个已解决,另一个已拒绝。

输出结果如下:

fileOf7174.png

5、async/await 的错误处理

JavaScript 中的 async/await 表示异步函数,用同步的方式去编写异步,可读性更好。

下面来改编上面的同步函数 toUppercase,通过将 async 放在 function 关键字之前将其转换为异步函数:

async function toUppercase(string) {if (typeof string !== "string") {throw TypeError("Expected string");}return string.toUpperCase();
}

只需在 function 前加上 async 前缀,就可以让函数返回一个 Promise。这意味着我们可以在函数调用之后链式调用 then、catch 和 finally:

toUppercase("hello").then(result => console.log(result)).catch(error => console.error(error.message)).finally(() => console.log("Always runs!"));

当从 async 函数中抛出异常时,异常会成为底层 Promise 被拒绝的原因。任何错误都可以从外部用 catch 拦截。

除此之外,还可以使用 try/catch/finally 来处理错误,就像在同步函数中一样。

例如,从另一个函数 consumer 中调用 toUppercase,它方便地用 try/catch/finally 包装了函数调用:

async function toUppercase(string) {if (typeof string !== "string") {throw TypeError("Expected string");}return string.toUpperCase();
}async function consumer() {try {await toUppercase(98);} catch (error) {console.error(error.message);} finally {console.log("Finally");}
}consumer();

输出结果如下:

fileOf7174.png

6、异步生成器的错误处理

JavaScript 中的异步生成器是能够生成 Promise 而不是简单值的生成器函数。它将生成器函数与异步相结合,结果是一个生成器函数,其迭代器对象向消费者公开一个 Promise。

要创建一个异步生成器,需要声明一个带有星号 * 的生成器函数,前缀为 async:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad!"); // Promise.reject
}

因为异步生成器是基于 Promise,所以同样适用 Promise 的错误处理规则,在异步生成器中,throw 会导致 Promise 拒绝,可以用 catch 拦截它。

要想从异步生成器处理 Promise,可以使用 then:

const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));
go.next().catch(reason => console.error(reason.message));

输出结果如下:

fileOf7174.png

也使用异步迭代 for await...of。 要使用异步迭代,需要用 async 函数包装 consumer:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad"); // Promise.reject
}async function consumer() {for await (const value of asyncGenerator()) {console.log(value);}
}consumer();

与 async/await 一样,可以使用 try/catch 来处理任何异常:

async function* asyncGenerator() {yield 33;yield 99;throw Error("Bad"); // Promise.reject
}async function consumer() {try {for await (const value of asyncGenerator()) {console.log(value);}} catch (error) {console.error(error.message);}
}consumer();

输出结果如下:

fileOf7174.png

从异步生成器函数返回的迭代器对象也有一个  throw()  方法。在这里对迭代器对象调用 throw() 不会抛出异常,而是 Promise 拒绝:

async function* asyncGenerator() {yield 33;yield 99;yield 11;
}const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));go.throw(Error("Reject!"));go.next().then(value => console.log(value)); 

输出结果如下:

fileOf7174.png

可以通过以下方式来捕获错误:

go.throw(Error("Let's reject!")).catch(reason =>console.error(reason.message)
);

我们知道,迭代器对象的 throw() 是在生成器内部发送异常的。所以还可以使用以下方式来处理错误:

async function* asyncGenerator() {try {yield 33;yield 99;yield 11;} catch (error) {console.error(error.message);}
}const go = asyncGenerator();go.next().then(value => console.log(value));
go.next().then(value => console.log(value));go.throw(Error("Reject!"));go.next().then(value => console.log(value));

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于人体姿势博文文章

MATLAB运动目标检测系统应用背景 运动目标的定位跟踪,检测识别,运动分析在图像压缩、运动分析、交通检测,智能监控等方面有主要的应用。 首先,在图像压缩中,运动目标检测技术可以在背景区域中将前景区域提取分割出来…

91.【C语言】数据结构之单向链表的查找,中间插入和删除,销毁

目录 1.链表的查找函数 2.链表的修改函数 3.链表的中间插入函数 1.在pos之前插入:SLTInsertBefore函数 1.借助头指针pphead 示意图 代码示例(写入SList.c) 头文件添加SLTInsertbefore的声明 main.c的部分代码改为 1.测试中间插入 2.测试头部插入 3.测试pos为NULL的…

机器视觉:9点标定的原理与实现

一、什么是标定 标定就是将机器视觉处理得到的像素坐标转换成实际项目中使用到的毫米坐标。简单说即使看看实际单位距离内有几个像素,如下图所示,10mm的距离内有222个像素,那像素坐标和实际的毫米坐标就有个比例关系了。 二、九点标定 9点标…

API网关的作用--为什么微服务需要一个API网关?

微服务网关核心作用就是协议转换、安全隔离和流量控制 微服务架构中,API网关作为系统的入口点,可以统一处理所有客户端请求。 1)协议转换:它能够支持多种通信协议(如HTTP、gRPC等)之间的相互转换&#xff…

React Native 持久化数据

在 React Native 中,持久化数据是指将数据保存在设备上,以便在应用重新启动后仍然可以访问。以下是一些常用的数据持久化方法: AsyncStorage: React Native 提供了 react-native-async-storage/async-storage 库,这是一…

如何初始化一个线上的GitHub仓库,在本地已有的仓库中上传到线上

如何初始化一个线上的GitHub仓库,在本地已有的仓库中上传到线上, 首先,先创建一个线上的仓库 本地有一个曾经的仓库,或者本地git init创建一个本地仓库 根据线上仓库的主页给的提示代码进行上传 代码如下: …or cr…

gateway 整合 spring security oauth2

微服务分布式认证授权方案 在分布式授权系统中,授权服务要独立成一个模块做统一授权,无论客户端是浏览器,app或者第三方,都会在授权服务中获取权限,并通过网关访问资源 OAuth2的四种授权模式 授权码模式 授权服务器将授…

(三)行为模式:11、模板模式(Template Pattern)(C++示例)

目录 1、模板模式含义 2、模板模式的UML图学习 3、模板模式的应用场景 4、模板模式的优缺点 5、C实现的实例 1、模板模式含义 模板模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法骨架,将某些步骤…

LeetCode9:回文数

原题地址:. - 力扣(LeetCode) 题目描述: 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数 是指正序(从左向右)和倒序&#xff…

java 大集合切分成一个集合中有多个小集合

直接上代码 List<OtsAttendance> otsAttendanceList new ArrayList<>(); 举个例子 otsAttendanceList 该集合里面有很多个对象。 那么如果批量新增的话&#xff0c;不太好&#xff0c;需要拆分成, &#xff08;一个集合&#xff0c;然后泛型又是一个集合&#xf…

故障诊断 | CNN-ResNets滚动轴承故障诊断实例代码

故障诊断 | CNN-ResNets滚动轴承故障诊断实例代码 目录 故障诊断 | CNN-ResNets滚动轴承故障诊断实例代码效果一览基本介绍程序设计参考资料 效果一览 基本介绍 CNN-ResNets&#xff08;卷积神经网络-残差网络&#xff09;在滚动轴承故障诊断中是一种常用的方法。这种方法利用…

Docker 实践与应用举例教程:从入门到精通

Docker 实践与应用举例教程&#xff1a;从入门到精通 引言 在现代软件开发中&#xff0c;Docker 已成为一种不可或缺的工具。它通过容器化技术简化了应用的部署、管理和扩展&#xff0c;极大地提高了开发和运维的效率。本文将详细介绍 Docker 的基本概念、安装步骤、常用命令…

arm ubuntu22.04 安装es7.16.2

1、更新软件包 sudo apt update && sudo apt upgrade -y 2、安装jdk11 sudo apt install openjdk-11-jdk -y 安装查看版本 java -version 输出应该是这样的 openjdk version "11.0.11" 2021-04-20 OpenJDK Runtime Environment (build 11.0.119-Ub…

openjdk17 hotspot JVM解析class文件

##openjdk17 hotspot JVM解析class文件 ClassFileParser::parse_stream 解析字节码 void ClassFileParser::parse_stream(const ClassFileStream* const stream,TRAPS) {assert(stream ! NULL, "invariant");assert(_class_name ! NULL, "invariant");//…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22目录1. PoisonedRAG: Knowledge corruption attacks to retrieval-augmented generation of large language models摘要创新点…

MySQL数据库学习指南

一、数据库的库操作 1、创建数据库 2、删除数据库 3、查看数据库 4、选择数据库 5、修改数据库 6、数据库备份与恢复 7、数据库的权限管理 二、数据库的表操作 1、创建表 2、删除表 3、修改表 4、查看表的结构 5、查看表的数据 6、创建索引 7、删除索引 8、约束…

Java程序设计:spring boot(8)——API ⽂档构建⼯具 - Swagger2

目录 1 环境整合配置 2 Swagger2 常⽤注解说明 2.1 Api 2.2 ApiOperation 2.3 ApiImplicitParams 2.4 ApiResponses 2.5 ApiModel 3 用户模块注解配置 3.1 Controller 使用注解 3.2 JavaBean 使用注解 4 Swagger2 接⼝⽂档访问 由于 Spring Boot 能够快速开发、便捷…

duilib的应用 在双屏异分辨率的显示器上 运行显示不出来

背景&#xff1a;win11&#xff0c;duilib应用&#xff0c;双显示器&#xff0c;两台分辨率相同&#xff0c;分别设置不同的缩放以后&#xff0c;应用运行以后&#xff0c;程序闪一下消失或者程序还在&#xff0c;但是UI显示不出来。 原因 窗口风格设置不合理&#xff0c;所以…

NumPy 数组合并与修改示例解析

一、代码示例 以下是完整的代码段: import numpy as np# 初始化两个数组 x 和 y x = np.array([[1.0, 2.0], [3.0, 4.0]]) y = np.array([[5.0, 6.0], [7.0, 8.0]])# 输出 x 和 y 的形状 print(x.shape, y.shape)# 沿第 0 轴(垂直方向)合并 x 和 y z = np.concatenate((x,…

2024.10.9华为留学生笔试题解

第一题无线基站名字相似度 动态规划 考虑用动态规划解决 char1=input().strip() char2=input().strip() n,m=len(char1),len(char2) dp=[[0]*(m+1) for _ in range(n+1)] #dp[i][j]定义为以i-1为结尾的char1 和以 j-1为结尾的char2 的最短编辑距离 setA = set(wirel@com) set…