首页 > 其他分享 >async/await 函数到底要不要加 try catch ?

async/await 函数到底要不要加 try catch ?

时间:2024-09-30 16:44:45浏览次数:8  
标签:中断 await try let userInfo reject catch

前言

写异步函数的时候,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 链式写法,感觉没必要。

标签:中断,await,try,let,userInfo,reject,catch
From: https://www.cnblogs.com/ranyihang/p/18442140

相关文章

  • HarmonyOs DevEco Studio小技巧24--异步编程(Promises、async/await)
    异步编程:调用后耗时,不阻塞代码继续执行,将来完成后,触发回调函数传递结果异步编程的范畴:网络请求(如使用 fetch 或 XMLHttpRequest 发送HTTP请求获取数据)。文件读写操作(读取或写入本地文件)。数据库操作(查询、插入、更新、删除数据)。定时器函数(如 setTimeout 和 setInt......
  • CHI trans简介--Retry
    总目录:CHI协议简读汇总-CSDN博客Retrytransflowrequester发送一个请求,该请求没有protocolcredit(P-Credit);也就是说,该请求不保证completer一定能够接收该trans;completer返回一个retryresp,RetryAck,给到Requester;completer再发送一个protocolcreditgrant,PCr......
  • CVEN9612 – Catchment Modelling
    CVEN9612–CatchmentModellingAssignment1Part1–Rainfall-RunoffModelingandRoutinghispartoftheassignmentisworth15%ofthetotalgradeforCVEN9612.TheassignmentanswersaretobesubmittedonlineinMoodleasashortreport.Assignment1......
  • Registry私有仓库可视化
    Registry私有仓库可视化一、简介        私有DockerRegistry通常用于企业内部或特定团队中存储和管理Docker镜像。随着项目的发展,镜像数量不断增加,管理起来变得越来越复杂。使用可视化的工具可以帮助管理员和开发者更直观地查看和管理这些镜像,从而提高工作效率......
  • 第六届经济管理与文化产业国际学术会议 2024 6th International Conference on Econom
    文章目录一、会议详情二、重要信息三、大会介绍四、出席嘉宾五、征稿主题六、咨询一、会议详情二、重要信息大会官网:https://ais.cn/u/vEbMBz提交检索:EICompendex、IEEEXplore、Scopus大会时间:2024年10月25-27日大会地点:中国-大连三、大会介绍抓住数字经济的......
  • docker本地搭建docker-registry及ui
    version:"3.7"services:registry-ui:image:joxit/docker-registry-ui:mainrestart:alwaysports:-5080:80environment:-SINGLE_REGISTRY=true-REGISTRY_TITLE=DockerRegistryUI-DELETE_IMAGES=true......
  • c# async await详解
    asyncawait传染性async/await具有传染性其实指的是你需要把异步函数的结果包装在Task类型当中。之所以c#要加async的主要原因是之前的await不是关键字,老代码可能会把await作为变量名,为了兼容性才加了async明确标识函数是continuation。await不能省略,在语义上有违直觉,为什么T......
  • C# Linq.FirstOrDefault、Linq.Where、Linq.AsParallel、List.Exists、List.Find、Dic
    C#Linq.FirstOrDefault、Linq.Where、Linq.AsParallel、List.Exists、List.Find、Dictionar.TryGetValue、HashSet.Contains性能的比较 今天我们来比较一下集合检索方法性能更优问题,测试代码publicclassEntity{publicintId{get;set;}publicintNo{......
  • Thread , ThreadLocal , ThreadLocalMap , Entry 之间的关系?
    Thread,ThreadLocal,ThreadLocalMap,Entry之间的关系?首先ThradLocal是线程的本地副本,怎么理解这句话呢?一个Thread都有一个它自己的ThreadLocalMap。ThreadLocalMap不是HashMap的结构,而是一个Entry数组,里面存放了一个一个的Entry。而Entry中存放的就是key和value,这个......
  • 初步学习async/await,Task.GetAwaiter,Task.Result
    初步学习async/await,Task.GetAwaiter,Task.Result   网上关于async/await的知识有很多,看了很多但不如自己实践一遍来得快,所以这里记录下我的理解和大家学习下。  首先以最简单的同步方法来开始如下privatestaticvoidTest(){Console.Wr......