停止使用 try-catch 来捕获异步/等待异常

首先,让我解释一下,try-catch 处理没有错。我认为以这种方式编写代码会有点混乱。我觉得代码的逻辑被破坏了,很难理解。

二是代码冗余问题。单个 try-catch 会占用多行代码。如果向每个请求添加了 try-catch,则代码将显示为臃肿。

而对于如此大量的相同冗余代码,可以用通用功能代替。
async/await 在 ES2017 中引入,旨在让异步操作更加直观方便,并解决 Promise 回调地狱问题。

1. 何时申请例外

我们都知道,这通常跟着异步请求。异步请求异常的原因大致如下:await

由于网络问题,网络断开连接,请求不可用

慢速网络会导致异步请求超时。

2. 在什么情况下需要处理请求异常?

一旦出现上述情况,异步请求就会产生异常,JavaScript 是一种单线程语言。代码报错后,后续代码无法继续执行,此时需要添加 try-catch 来捕获异步请求。异常,以便代码可以继续向后执行。

但是,是否有必要为所有异步请求添加 try-catch?

我研究了我们项目的代码。异步请求使用 try-catch 进行处理。有以下几种情况。

2.1 多异步请求串行

js
try {  const list = await getList(params)  const info = await getListById(list[0]?.id)} catch {}

上一个异步请求的返回结果会作为下一个异步请求的请求参数,所以一旦上一个请求异常,后续请求就会异常,所以需要添加 try-catch 处理。

2.2 处理异步请求的加载状态

js
loading.value = truetry {  const list = await getList(params)} finally {  loading.value = false}

一般来说,在我们处理异步请求之前,我们会给它添加一个加载状态,一旦出现请求异常,如果我们不添加 try-catch,页面将始终处于加载状态。因此,最后需要将加载状态设置为 false,并且在 catch 中处理时需要外部处理。

那么,我们如何优雅地处理异步请求中的 try-catch?

3. 处理承诺

首先,需要明确的是:在正常情况下,await 命令后面跟着一个 Promise 对象。因此,它可以使用自身来捕获异常。就像上面第二个只处理加载状态的操作一样,可以在 .catch 中处理,然后使用 if 判断来控制提前退出。无需编写 try-catch 冗余代码。.catch

js
loading.value = truelet res = await getList().catch(() => (loading.value = false))if (!res) return

**await-to-js**处理程序函数

我们可以将上述方法用于简单的异步请求,但是当遇到多个异步操作时,我们需要使用我们今天要讨论的库。它的介绍非常简单:可以轻松执行,而不会发生 try-catch 句柄错误。await-to-js

而且源码很简单,只有23行代码,一起来看看吧。

js
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

一般流程如下:接受参数 Promise 和 .如果承诺成功,它将返回 。如果异常,它将判断它是否有参数(表示传递给 err 对象的附加信息)。如果它有时与捕获返回捕获的错误合并,或者如果没有。errorExt``[null, data]``errorExt``[err, undefined]

4. 如何使用

4.1 安装

bash
# use npmnpm i await-to-js --save# use yarnyarn add await-to-js

4.2 使用

首先介绍一下to函数,可以看到包很小,只有370b,gzip压缩后只有242b,所以随意导入,不用担心包大小。

我们用来重写上面的第一个问题:

js
import to from const [err, data] = await to(getList(params))if (err) returnconst info = await to(getListById(list[0]?.id))

函数转换后,如果返回的第一个参数不为空,则表示请求报错,可以提前返回。如果没有第一个参数,则异步请求成功。to

最后更新:2023-12-09