LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[转帖]async/await 函数到底要不要加 try catch ?

freeflydom
2023年7月24日 17:17 本文热度 468

前言

写异步函数的时候,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 可以正常捕获异常,但是程序没有中断,返回值 userInfoundefined, 所以如果这样写的话,就需要对返回值进行非空校验,  if (!userInfo) return 我觉得这样有点反逻辑,异常时就应该中断执行才对;

示例3:在 catch  里 reject

可以继续优化,在 catch 里面加一行 return Promise.reject(e), 可以使 await 中断执行;

完整代码:

function getUserInfo () {

    return new Promise((resolve, reject) => {

        setTimeout(() => {

            reject('请求异常')

        }, 1000)

    })

}


async function logined () {

    let userInfo = await getUserInfo().catch(e => {

        console.warn(e)

        return Promise.reject(e) // 会导致控制台出现 uncaught (in promise) 报错信息

    })

    // 执行中断

    let pageInfo = await getPageInfo(userInfo?.userId)

}


logined()


一般我们在项目里都是用 axios 或者 fetch 之类发送请求,会对其进行一个封装,也可以在里面进行 catch 操作,对错误信息先一步处理,至于是否需要 reject,就看你是否想要在 await 命令异常时候中断了;不使用 reject 则不会中断,但是需要每个接口拿到 response 后先 非空校验, 使用 reject 则会在异常处中断,并且会在控制台暴露  uncaught (in promise)  报错信息。

建议

不需要在 await 处异常时中断,可以这样写,需要做非空校验,控制台不会有报错信息

let userInfo = await getUserInfo().catch(e => console.warn(e))

if (!userInfo) return



需要在 await 处异常时中断,并且在意控制台报错,可以这样写

try {

    let userInfo = await getUserInfo()

    // 执行中断

    let pageInfo = await getPageInfo(userInfo?.userId)

} catch(e) {

    console.warn(e)

}


需要在 await 处异常时中断,但是不在意控制台报错,则可以这样写

let userInfo = await getUserInfo().catch(e => {

    console.warn(e)

    return Promise.reject(e) // 会导致控制台出现 uncaught (in promise) 报错信息

})

// 执行中断

let pageInfo = await getPageInfo(userInfo?.userId)


总结

几种写法,初看可能觉得第三种 catch 这种写法是最好的,但是细想下,从用户体验上来看,我觉得 try catch 是最好的,逻辑直观、符合同步编程思维,控制台不会暴露 uncaught (in promise) 报错信息;

而链式调用的 catch (里面再 reject),是传统 promise 的回调写法,既然已经用 async await 这种同步编程写法了,再用 catch 链式写法,感觉没必要。


原文链接



该文章在 2023/7/24 17:17:44 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved