缘由

JS中async/await异步调用,只能通过try-catch吗?

你想听的故事:

作为一个合格的全栈搬砖工,那必须文武双全,前后必备。遂吾日三省吾身,偶发觉前端长时间不写有些落下,便抽用了摸鱼的时间,检查一下前端小老弟的代码。

不查不知道,一查吓一跳。乍一看小老弟代码清新脱俗,特别规整,但存重大的隐患:



不知道大家看没看出,里面竟然没有异常捕获,完全逻辑代码一把嗦。可能有小伙伴说,我平时也这么写,也没遇到什么大坑,大不了页面报错呗,改就完了。

话虽如此,有坑没趟上,不代表永远顺风输水,如果不进行异常捕获,那么页面逻辑可能会因为此处异常戛然而止,导致后续业务无法正常执行

光描述可能小伙伴还是没有代码上概念,下面举一个例子便一目了然

举个栗子

有个页面,需要展示会员信息和推荐商品,前端页面需要调用后端接口并把两者赋值,显示到页面上

正常情况:调异步接口正常返回

此处模拟前端调用后端两个接口,分别获取会员信息商品信息两者互不影响,并打印。

小伙伴们可以看到,和我们预想一样,没有趟坑,非常顺利,没有任何问题

// 实例模拟页面初始化调用两个异步接口,并打印成功返回的数据
const getMember = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取会员数据
setTimeout(() => {
// 成功返回
resolve(
{
name: '张三',
age: 18
}
)
}, 1000)
})
} const getGoods = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取商品数据
setTimeout(() => {
// 成功返回
resolve(
[{
name: '面包',
price: 5
},{
name: '牛奶',
price: 6
}]
)
}, 2000)
})
} const init = async () => {
const member = await getMember();
console.log("会员:", member) const goods = await getGoods();
console.log("商品:", JSON.stringify(goods))
} init(); // 打印结果
// 会员: { name: '张三', age: 18 }
// 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]


异常情况:调异步接口且未捕获异常

此处同上模拟前端调用后端两个接口,此时会员信息接口出现问题异常,商品信息接口正常

小伙伴们可以看到,此时就掉入没有捕获异常的的坑了,非常遗憾,后续牵连接口一并因错误戛然而止,出错连坐!

// 实例模拟页面初始化调用两个异步接口,第一个获取会员信息异常,第二个商品数据正常
const getMember = async () => {
return new Promise((resolve, reject) => {
// 模拟获取会员数据接口异常
setTimeout(() => {
// 成功返回
reject(new Error('会员接口异常'))
}, 1000)
})
} const getGoods = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取商品数据
setTimeout(() => {
// 成功返回
resolve(
[{
name: '面包',
price: 5
},{
name: '牛奶',
price: 6
}]
)
}, 2000)
})
} const init = async () => {
const member = await getMember();
console.log("会员:", member) const goods = await getGoods();
console.log("商品:", JSON.stringify(goods))
} init(); // 打印结果
// 直接报异常,并且后面正常的商品接口console.log都没有打印内容

这种情况就导致,后续无关接口也无法正常返回,从而页面可能直接崩溃

综上案例,所以异常必须捕获,而且要捕获的漂亮


主要目标

实现重点

async/await异常捕获方法

正文

目标解析

async/await异常捕获方法

方法一:try-catch

任何异步调用全部一把嗦,全部套上try-catch壳

还是以上述内容为案例,将调用接口加入try-catch后,第一个接口异常后,后续接口不受影响

try{
// 加入try-catch异常捕获
const member = await getMember();
console.log("会员:", member)
}catch (e){
console.error("会员接口异常:", e)
}
// 完整代码
const getMember = async () => {
return new Promise((resolve, reject) => {
// 模拟获取会员数据接口异常
setTimeout(() => {
// 成功返回
reject(new Error('会员接口异常'))
}, 1000)
})
} const getGoods = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取商品数据
setTimeout(() => {
// 成功返回
resolve(
[{
name: '面包',
price: 5
},{
name: '牛奶',
price: 6
}]
)
}, 2000)
})
} const init = async () => {
try{
// 加入try-catch异常捕获
const member = await getMember();
console.log("会员:", member)
}catch (e){
console.error("会员接口异常:", e)
} try{
// 加入try-catch异常捕获
const goods = await getGoods();
console.log("商品:", JSON.stringify(goods))
}catch (e){
console.error("商品异常:", e)
}
} init(); // 打印结果
// 会员接口异常:xxxxx
// 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]

try-catch的弊端

接口少还好说,无脑加;接口多就会出现大批的try-catch军团,代码冗余并且十分混乱,阅读十分吃力!


方法二:使用 Promise 处理

解释一下:await 命令后面是一个 Promise 对象,直接可以使用.catch来捕获异常

// 直接后面跟着.catch
const member = await getMember().catch((err) => {console.error("会员接口异常:", err)});
// 完整代码
//
const getMember = async () => {
return new Promise((resolve, reject) => {
// 模拟获取会员数据接口异常
setTimeout(() => {
// 成功返回
reject(new Error('会员接口异常'))
}, 1000)
})
} const getGoods = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取商品数据
setTimeout(() => {
// 成功返回
resolve(
[{
name: '面包',
price: 5
},{
name: '牛奶',
price: 6
}]
)
}, 2000)
})
} const init = async () => {
// 加入.catch异常捕获
const member = await getMember().catch((err) => {console.error("会员接口异常:", err)});
if(member){
console.log("会员:", member)
// 处理会员业务逻辑...
} // 加入.catch异常捕获
const goods = await getGoods().catch((err) => {console.error("商品接口异常:", err)});
if(goods){
console.log("商品:", JSON.stringify(goods));
// 处理商品业务逻辑...
} } init(); // 打印结果
// 会员接口异常:xxxxx
// 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]

方法三:使用 await-to-js插件库

  • await-to-js是什么

await-to-js 是一个辅助开发者处理异步错误的库

  • await-to-js怎么下
# npm安装
npm i await-to-js --save
# yarn安装
yarn add await-to-js
  • await-to-js怎么写
import to from 'await-to-js'
const init = async () => {
const [err, data] = await to(getMember())
if (err){
console.error("会员接口异常:", err)
return
}
console.log("会员:", data) const [err1, data1] = await to(getGoods())
if (err1){
console.error("商品接口异常:", err1)
return
}
console.log("商品:", JSON.stringify(data1))
}
// 完整代码
import to from 'await-to-js'
const getMember = async () => {
return new Promise((resolve, reject) => {
// 模拟获取会员数据接口异常
setTimeout(() => {
// 成功返回
reject(new Error('会员接口异常'))
}, 1000)
})
} const getGoods = async () => {
return new Promise((resolve, reject) => {
// 模拟接口获取商品数据
setTimeout(() => {
// 成功返回
resolve(
[{
name: '面包',
price: 5
},{
name: '牛奶',
price: 6
}]
)
}, 2000)
})
} const init = async () => {
const [err, data] = await to(getMember())
if (err){
console.error("会员接口异常:", err)
return
}
console.log("会员:", data) const [err1, data1] = await to(getGoods())
if (err1){
console.error("商品接口异常:", err1)
return
}
console.log("商品:", JSON.stringify(data1))
} init(); // 打印结果
// 会员接口异常:xxxxx
// 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]
  • await-to-js源码分析
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error>(
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data])
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt)
return [parsedError, undefined]
} return [err, undefined]
})
} export default to

分析一下:

to方法入参是promise对象和自定义异常

如果没有异常则直接返回[null, data],数组第一项是异常信息为null,第二项为正常数据

如果捕获异常在catch中组装[err, undefined] 错误信息,数组第一项是异常信息为err,第二项数据为null


总结

本文通过async/await为切入点,介绍三种异步调用处理异常的方法:分别是try-catch、promise处理、await-to-js插件库处理。

希望小伙伴能学以致用,精进代码的同时,也让别人看我们代码时,变得易读好上手,人如其码!


猜你想问

如何与狗哥联系进行探讨

关注公众号【JavaDog程序狗】

公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过200+个小伙伴啦,只能拉人入群啦!!!

2.踩踩狗哥博客

javadog.net

大家可以在里面留言,随意发挥,有问必答


猜你喜欢

文章推荐

【规范】看看人家Git提交描述,那叫一个规矩

【工具】用nvm管理nodejs版本切换,真香!

【苹果】SpringBoot监听Iphone15邮件提醒,Selenium+Python自动化抢购脚本

【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!

【ChatGPT】手摸手,带你玩转ChatGPT

【ChatGPT】SpringBoot+uniapp+uview2对接OpenAI,带你开发玩转ChatGPT


【JS】await异常捕获,这样做才完美的更多相关文章

  1. js的异常捕获

    try{ ...some code... }catch(e){ ...some code... //处理错误 throw(e.name); //抛出异常 }finally{<BR> // ...

  2. Js全局异常捕获

    重新window.onerror方法就行了 window.onerror = handleError function handleError(msg,url,l) { var txt="T ...

  3. 异常捕获 崩溃 Bugly ACRC 简介 总结 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  5. atitit.js浏览器环境下的全局异常捕获

    atitit.js浏览器环境下的全局异常捕获 window.onerror = function(errorMessage, scriptURI, lineNumber) { var s= JSON. ...

  6. JS异常捕获和抛出

    try...catch 用来异常捕获(主要适用于IE5以上内核的浏览器,也是最常用的异常捕获方式) 使用onerror时间捕获异常,这种捕获方式是比较古老的一中方式,目前一些主流的浏览器暂不支持这种 ...

  7. JavaScript异常捕获

    理论准备 ★   异常捕获 △ 异常:当JavaScript引擎执行JavaScript代码时,发生了错误,导致程序停止运行: △ 异常抛出:当异常产生,并且这个异常生成一个错误信息: △ 异常捕获: ...

  8. iOS异常捕获

    文章目录 一. 系统Crash 二. 处理signal 下面是一些信号说明 关键点注意 三. 实战 四. Crash Callstack分析 – 进⼀一步分析 五. demo地址 六. 参考文献 前言 ...

  9. T-SQL编程中的异常处理-异常捕获(catch)与抛出异常(throw)

    本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出,本文简单介绍异常捕获与异 ...

  10. Spring AOP异常捕获原理

    Spring AOP异常捕获原理:        被拦截的方法,须显式的抛出异常,且不能做任何处理, 这样AOP才能捕获到方法中的异常,进而进行回滚.        换句话说,就是在Service层的 ...

随机推荐

  1. mongodb基础整理篇————聚合操作[三]

    前言 简单整理一下聚合操作. 正文 什么是聚合框架: 作用于一个或多个集合上 对集合的数据进行的一系列运算 将这些数据转换为期望的形式 从效果而言, 聚合框架相当于SQL 查询中的: Group By ...

  2. RestfulApi 学习笔记——.net core入门操作(二)

    前言 前面简单介绍了一下restfulapi是什么东西,那么我们应该在.net core 中如何实现呢?或者说该怎么做才能有这个restful api呢? 正文 幸运的是.net core帮助我们实现 ...

  3. lowdb 在electron 使用中注意的问题

    前言 可能很多人都没有听说过这个lowdb,但是它的确存在,而且在electron 中用到还是挺多的. 如何在electron 的render 进程中是引用electron 模块. 我们知道一个问题, ...

  4. Pytorch风格迁移代码

    最近研究了一下风格迁移,主要是想应用于某些主题节日时动态融合背景,生成一些抽象的艺术图片,这里给大家分享一个现成的代码,我本地把环境搭建好后跑了试试,有兴趣的可以直接拿去运行: 1 import to ...

  5. 文本溢出显示省略号css

    项目中常常有这种需要我们对溢出文本进行"..."显示的操作,单行多行的情况都有(具体几行得看设计师心情了),这篇随笔是我个人对这种情况解决办法的归纳,欢迎各路英雄指教. 单行 语法 ...

  6. 力扣59(java)-螺旋矩阵Ⅱ(中等)

    题目: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix . 输入:n = 3 输出:[[1,2,3],[8,9,4],[ ...

  7. 阿里云 EMR Delta Lake 在流利说数据接入中的架构和实践

    简介: 为了消灭数据孤岛,企业往往会把各个组织的数据都接入到数据湖以提供统一的查询或分析.本文将介绍流利说当前数据接入的整个过程,期间遇到的挑战,以及delta在数据接入中产生的价值. 背景 流利说目 ...

  8. Flagger on ASM·基于Mixerless Telemetry实现渐进式灰度发布系列 1 遥测数据

    简介: 服务网格ASM的Mixerless Telemetry技术,为业务容器提供了无侵入式的遥测数据.遥测数据一方面作为监控指标被ARMPS/prometheus采集,用于服务网格可观测性:另一方面 ...

  9. 从0开始:500行代码实现 LSM 数据库

    简介: LSM-Tree 是很多 NoSQL 数据库引擎的底层实现,例如 LevelDB,Hbase 等.本文基于<数据密集型应用系统设计>中对 LSM-Tree 数据库的设计思路,结合代 ...

  10. 深入解读 Flink SQL 1.13

    简介: Apache Flink 社区 5 月 22 日北京站 Meetup 分享内容整理,深入解读 Flink SQL 1.13 中 5 个 FLIP 的实用更新和重要改进. 本文由社区志愿者陈政羽 ...