文章主要讨论了在使用async函数时,try catch语句在捕获异常方面的应用及其在不同场景下的使用考量。文章提供了三个代码示例来展示不同的处理方式,并对此进行了分析与比较。
文章开头引发了关于如何使用try catch来捕获async函数中的异常的讨论,并提出了不同开发者有不同的使用习惯。
在第一个示例中,文章展示了如何在async函数中使用try catch来捕获异常,当出现异常时,函数会中断执行。
第二个示例展示了如何在没有try catch的情况下使用await后面的Promise对象的catch方法来捕获异常,但这样做会导致程序不会中断执行,需要对返回值进行非空校验。
第三个示例展示了在catch里使用reject的优化方式,可以在出现异常时使await中断执行,但可能会导致控制台出现uncaught (in promise)报错信息。
文章最后总结了几种写法的优缺点,并给出了建议,认为try catch逻辑直观、符合同步编程思维,且控制台不会暴露uncaught (in promise)报错信息,可能是最好的选择。
前言
写异步函数的时候,promise 和 async 两种方案都非常常见,甚至同一个项目里,不同的开发人员都使用不同的习惯, 不过关于两者的比较不是本文关注的重点,只总结为一句话:“async 是异步编程的终极解决方案”。
当使用 async 函数的时候,很多文章都说建议用
try catch
来捕获异常, 可是实际上我看了很多项目的代码,遵循的并不是严谨,很多都没有用,甚至 catch 函数都没写,这是为什么呢?
我们先看下使用 try catch 情况下的代码示例:
示例1 :使用 try catch
function getUserInfo () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求异常')
}, 1000)
})
}
async function logined () {
try {
let userInfo = await getUserInfo()
// 执行中断
let pageInfo = await getPageInfo(userInfo?.userId)
} catch(e) {
console.warn(e)
}
}
logined()
复制代码
执行后会在 catch 里捕获
请求异常
,然后 getUserInfo 函数中断执行,这是符合逻辑的,对于有依赖关系的接口,中断执行可以避免程序崩溃,这里唯一的问题是 try catch 貌似占据了太多行数,如果每个接口都写的话看起来略显冗余。
示例2:直接 catch
鉴于正常情况下,
await
命令后面是一个 Promise 对象, 所以上面代码可以很自然的想到优化方案:
function getUserInfo () {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求异常')
}, 1000)
})
}
async function logined () {
let userInfo = await getUserInfo().catch(e => console.warn(e))
// 执行没有中断,userInfo 为 undefined
if (!userInfo) return // 需要做非空校验
let pageInfo = await getPageInfo(userInfo?.userId)
}
logined()
复制代码
执行后 catch 可以正常捕获异常,但是程序没有中断,返回值
userInfo
为
undefined
, 所以如果这样写的话,就需要对返回值进行非空校验,
if (!userInfo) return
我觉得这样有点反逻辑,异常时就应该中断执行才对;
示例3:在 catch 里 reject
可以继续优化,在 catch 里面加一行
return Promise.reject(e)
, 可以使 await 中断执行;