前言

我们一般都是使用 try-catch 来处理 async-await 异常,这样写本质上也没什么问题,async-await 异常处理的本质原因是:避免异步操作的报错导致接下去的代码都无法执行,所以需要添加异常处理。

多个异步请求串行

1
2
3
4
5
6
try {
// 获取列表list
const list = await getList(params);
// 获取单个详情
const info = await getListById(list[0]?.id);
} catch {}

前一个异步请求的返回结果,会作为后一个异步请求的请求参数使用,所以一旦前一个请求异常,后面的请求肯定会异常,所以需要添加 try-catch 处理。

但是存在一些问题,如果每一个 async-await 都这样来添加异常处理,会产生很多的冗余代码,而且代码整体看起来也不是很美观,感觉都是在重复,

简化异常处理的方法

使用 Promise 处理

首先需要明确一点:正常情况下,await 命令后面是一个 Promise 对象。所以它本身就可以使用.catch来捕获异常,那么像上面第二种只是处理 loading 状态的操作,完全可以在.catch进行处理,然后用if判断来控制提前退出,没必要写 try-catch 这种冗余代码。

1
2
3
4
loading.value = true;
let res = await getList().catch(() => (loading.value = false));
if (!res) return;
// 请求成功后正常操作

await-to-js 处理函数

简单的异步请求我们可以使用上面这种方法,但遇到多个异步操作时,就需要借助我们今天要说的 await-to-js 这个库,它的介绍很简单:无需 try-catch 即可轻松处理错误

而且源码贼简单,就 23 行代码,我们一起来看看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
@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接受参数PromiseerrorExt,如果这个 Promise 成功时返回[null, data],如果异常时会判断是否带有errorExt参数(代表传递给 err 对象的附加信息),如果有时会与 catch 捕获的 err 合并返回,如果没有时返回[err, undefined]

很简单的逻辑是不是,接着我们看下它的用法:

  • 安装

    1
    2
    3
    4
    # use npm
    npm i await-to-js --save
    # use yarn
    yarn add await-to-js
  • 使用

    首先引入to函数,可以看到包很小,只有 370b,gzip 压缩后只有 242b,所以放心引入,别担心什么包大小问题。

    图片

    await-to-js-size.png

    我们通过to来改写一下上面第一种问题:

    1
    2
    3
    4
    5
    6
    import to from "await-to-js";
    // 获取列表list
    const [err, data] = await to(getList(params));
    if (err) return;
    // 获取单个详情
    const info = await to(getListById(list[0]?.id));

    通过to函数改造后,如果返回第一个参数不为空时,说明该请求报错,就可以提前 return 出去,如果不存在第一个参数时,则异步请求成功。

总结

本文通过研究 async/await 的异常捕获,发现了两种常见的异步请求异常捕获,并提出了两种简单的解决方法。通过这两种方法,就可以丢掉冗余的 try-catch,然后你就会发现没了 try-catch 的代码看起来都是顺眼的。

很多小伙伴可能也会遇到这个问题:尽管你提出了解决方案,但依旧会有项目组成员不用。你要这么想就错了,自己通过研究、查资料,最终学到了东西就足够了,管别人干嘛!没必要啊。

以上就是本文的全部内容,希望这篇文章对你有所帮助,欢迎点赞和收藏 🙏,如果发现有什么错误或者更好的解决方案及建议,欢迎随时联系。