经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
【JS】await异常捕获,这样做才完美
来源:cnblogs  作者:JavaDog程序狗  时间:2024/5/29 9:20:41  对本文有异议

??缘由

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

??你想听的故事:

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

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


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

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

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

举个栗子??

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

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

此处模拟前端调用后端两个接口,分别获取会员信息商品信息两者互不影响,并打印。
小伙伴们可以看到,和我们预想一样,没有趟坑,非常顺利,没有任何问题

  1. // 实例模拟页面初始化调用两个异步接口,并打印成功返回的数据
  2. const getMember = async () => {
  3. return new Promise((resolve, reject) => {
  4. // 模拟接口获取会员数据
  5. setTimeout(() => {
  6. // 成功返回
  7. resolve(
  8. {
  9. name: '张三',
  10. age: 18
  11. }
  12. )
  13. }, 1000)
  14. })
  15. }
  16. const getGoods = async () => {
  17. return new Promise((resolve, reject) => {
  18. // 模拟接口获取商品数据
  19. setTimeout(() => {
  20. // 成功返回
  21. resolve(
  22. [{
  23. name: '面包',
  24. price: 5
  25. },{
  26. name: '牛奶',
  27. price: 6
  28. }]
  29. )
  30. }, 2000)
  31. })
  32. }
  33. const init = async () => {
  34. const member = await getMember();
  35. console.log("会员:", member)
  36. const goods = await getGoods();
  37. console.log("商品:", JSON.stringify(goods))
  38. }
  39. init();
  40. // 打印结果
  41. // 会员: { name: '张三', age: 18 }
  42. // 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]


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

此处同上模拟前端调用后端两个接口,此时会员信息接口出现问题异常,商品信息接口正常
小伙伴们可以看到,此时就掉入没有捕获异常的的坑了,非常遗憾,后续牵连接口一并因错误戛然而止,出错连坐!

  1. // 实例模拟页面初始化调用两个异步接口,第一个获取会员信息异常,第二个商品数据正常
  2. const getMember = async () => {
  3. return new Promise((resolve, reject) => {
  4. // 模拟获取会员数据接口异常
  5. setTimeout(() => {
  6. // 成功返回
  7. reject(new Error('会员接口异常'))
  8. }, 1000)
  9. })
  10. }
  11. const getGoods = async () => {
  12. return new Promise((resolve, reject) => {
  13. // 模拟接口获取商品数据
  14. setTimeout(() => {
  15. // 成功返回
  16. resolve(
  17. [{
  18. name: '面包',
  19. price: 5
  20. },{
  21. name: '牛奶',
  22. price: 6
  23. }]
  24. )
  25. }, 2000)
  26. })
  27. }
  28. const init = async () => {
  29. const member = await getMember();
  30. console.log("会员:", member)
  31. const goods = await getGoods();
  32. console.log("商品:", JSON.stringify(goods))
  33. }
  34. init();
  35. // 打印结果
  36. // 直接报异常,并且后面正常的商品接口console.log都没有打印内容

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

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


??主要目标

实现重点

async/await异常捕获方法

正文

??目标解析

async/await异常捕获方法

方法一:try-catch

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

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

  1. try{
  2. // 加入try-catch异常捕获
  3. const member = await getMember();
  4. console.log("会员:", member)
  5. }catch (e){
  6. console.error("会员接口异常:", e)
  7. }
  1. // 完整代码
  2. const getMember = async () => {
  3. return new Promise((resolve, reject) => {
  4. // 模拟获取会员数据接口异常
  5. setTimeout(() => {
  6. // 成功返回
  7. reject(new Error('会员接口异常'))
  8. }, 1000)
  9. })
  10. }
  11. const getGoods = async () => {
  12. return new Promise((resolve, reject) => {
  13. // 模拟接口获取商品数据
  14. setTimeout(() => {
  15. // 成功返回
  16. resolve(
  17. [{
  18. name: '面包',
  19. price: 5
  20. },{
  21. name: '牛奶',
  22. price: 6
  23. }]
  24. )
  25. }, 2000)
  26. })
  27. }
  28. const init = async () => {
  29. try{
  30. // 加入try-catch异常捕获
  31. const member = await getMember();
  32. console.log("会员:", member)
  33. }catch (e){
  34. console.error("会员接口异常:", e)
  35. }
  36. try{
  37. // 加入try-catch异常捕获
  38. const goods = await getGoods();
  39. console.log("商品:", JSON.stringify(goods))
  40. }catch (e){
  41. console.error("商品异常:", e)
  42. }
  43. }
  44. init();
  45. // 打印结果
  46. // 会员接口异常:xxxxx
  47. // 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]

try-catch的弊端

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


方法二:使用 Promise 处理

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

  1. // 直接后面跟着.catch
  2. const member = await getMember().catch((err) => {console.error("会员接口异常:", err)});
  1. // 完整代码
  2. //
  3. const getMember = async () => {
  4. return new Promise((resolve, reject) => {
  5. // 模拟获取会员数据接口异常
  6. setTimeout(() => {
  7. // 成功返回
  8. reject(new Error('会员接口异常'))
  9. }, 1000)
  10. })
  11. }
  12. const getGoods = async () => {
  13. return new Promise((resolve, reject) => {
  14. // 模拟接口获取商品数据
  15. setTimeout(() => {
  16. // 成功返回
  17. resolve(
  18. [{
  19. name: '面包',
  20. price: 5
  21. },{
  22. name: '牛奶',
  23. price: 6
  24. }]
  25. )
  26. }, 2000)
  27. })
  28. }
  29. const init = async () => {
  30. // 加入.catch异常捕获
  31. const member = await getMember().catch((err) => {console.error("会员接口异常:", err)});
  32. if(member){
  33. console.log("会员:", member)
  34. // 处理会员业务逻辑...
  35. }
  36. // 加入.catch异常捕获
  37. const goods = await getGoods().catch((err) => {console.error("商品接口异常:", err)});
  38. if(goods){
  39. console.log("商品:", JSON.stringify(goods));
  40. // 处理商品业务逻辑...
  41. }
  42. }
  43. init();
  44. // 打印结果
  45. // 会员接口异常:xxxxx
  46. // 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]

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

  • await-to-js是什么

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

  • await-to-js怎么下
  1. # npm安装
  2. npm i await-to-js --save
  3. # yarn安装
  4. yarn add await-to-js
  • await-to-js怎么写
  1. import to from 'await-to-js'
  2. const init = async () => {
  3. const [err, data] = await to(getMember())
  4. if (err){
  5. console.error("会员接口异常:", err)
  6. return
  7. }
  8. console.log("会员:", data)
  9. const [err1, data1] = await to(getGoods())
  10. if (err1){
  11. console.error("商品接口异常:", err1)
  12. return
  13. }
  14. console.log("商品:", JSON.stringify(data1))
  15. }
  1. // 完整代码
  2. import to from 'await-to-js'
  3. const getMember = async () => {
  4. return new Promise((resolve, reject) => {
  5. // 模拟获取会员数据接口异常
  6. setTimeout(() => {
  7. // 成功返回
  8. reject(new Error('会员接口异常'))
  9. }, 1000)
  10. })
  11. }
  12. const getGoods = async () => {
  13. return new Promise((resolve, reject) => {
  14. // 模拟接口获取商品数据
  15. setTimeout(() => {
  16. // 成功返回
  17. resolve(
  18. [{
  19. name: '面包',
  20. price: 5
  21. },{
  22. name: '牛奶',
  23. price: 6
  24. }]
  25. )
  26. }, 2000)
  27. })
  28. }
  29. const init = async () => {
  30. const [err, data] = await to(getMember())
  31. if (err){
  32. console.error("会员接口异常:", err)
  33. return
  34. }
  35. console.log("会员:", data)
  36. const [err1, data1] = await to(getGoods())
  37. if (err1){
  38. console.error("商品接口异常:", err1)
  39. return
  40. }
  41. console.log("商品:", JSON.stringify(data1))
  42. }
  43. init();
  44. // 打印结果
  45. // 会员接口异常:xxxxx
  46. // 商品: [{"name":"面包","price":5},{"name":"牛奶","price":6}]
  • await-to-js源码分析
  1. /**
  2. * @param { Promise } promise
  3. * @param { Object= } errorExt - Additional Information you can pass to the err object
  4. * @return { Promise }
  5. */
  6. export function to<T, U = Error>(
  7. promise: Promise<T>,
  8. errorExt?: object
  9. ): Promise<[U, undefined] | [null, T]> {
  10. return promise
  11. .then<[null, T]>((data: T) => [null, data])
  12. .catch<[U, undefined]>((err: U) => {
  13. if (errorExt) {
  14. const parsedError = Object.assign({}, err, errorExt)
  15. return [parsedError, undefined]
  16. }
  17. return [err, undefined]
  18. })
  19. }
  20. 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


原文链接:https://www.cnblogs.com/javadog-net/p/18215667

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号