停止使用 try-catch 捕捉 Async:Await 异常(译文)

First of all, let me explain that there is nothing wrong with try-catch processing. I think writing the code this way will be a bit messy. I feel that the logic of the code is broken and difficult to understand.

The second is the problem of code redundancy. A single try-catch takes up several lines of code. If a try-catch is added to each request, the code will appear bloated.

And for such a large number of identical redundant codes, it can be replaced by a general function.
async/await was introduced in ES2017 to make asynchronous operations more intuitive and convenient and solve the Promise callback hell problem.

首先,请允许我解释一下,try-catch 处理并没有错。我认为这样写代码会有点乱。我觉得代码的逻辑是支离破碎的,难以理解。

其次是代码冗余的问题。一个 try-catch 会占用几行代码。如果每个请求都添加一个 try-catch,代码就会显得臃肿。

而对于大量相同的冗余代码,可以用一个通用函数来代替。

ES2017 引入了 async/await,使异步操作更直观、更方便,并解决了 Promise 回调地狱问题。

【关于TalkX】

TalkX是一款基于GPT实现的IDE智能开发插件,专注于编程领域,是开发者在日常编码中提高编码效率及质量的辅助工具,TalkX常用的功能包括但不限于:解释代码、中英翻译、性能检查、安全检查、样式检查、优化并改进、提高可读性、清理代码、生成测试用例等。

TalkX建立了全球加速网络,不需要考虑网络环境,响应速度快,界面效果和交互体验更流畅。并为用户提供了OpenAI的密钥,不需要ApiKey,不需要自备账号,不需要魔法。

TalkX产品支持:JetBrains (包括 IntelliJ IDEA、PyCharm、WebStorm、Android Studio)、HBuilder、VS Code、Goland.

1. When will an exception be requested(何时申请例外)

We all know that awaitis usually followed by asynchronous requests. The reasons for abnormalities in asynchronous requests are roughly as follows:

Due to network problems, the network is disconnected and the request is not available

A slow network causes asynchronous requests to time out.

我们都知道,await后通常会出现异步请求。异步请求出现异常的原因大致如下:

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

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

2. Under what circumstances do you need to handle request exceptions(在什么情况下需要处理请求异常)?

Once the above situation occurs, the asynchronous request will generate an exception, and JavaScript is a single-threaded language. After the code reports an error, the subsequent code cannot continue to execute, so it is necessary to add a try-catch to capture the asynchronous request at this time. Exception, so that the code can continue to execute backward.

But is it necessary to add a try-catch for all asynchronous requests?

I have studied the code of our project. The asynchronous request is processed with a try-catch. There are the following situations.

一旦出现上述情况,异步请求就会产生异常,而 JavaScript 是一种单线程语言。代码报错后,后续代码无法继续执行,因此有必要添加一个 try-catch 来捕获此时的异步请求。异常,这样代码才能继续向后执行。

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

我研究了我们项目的代码。异步请求是通过 try-catch 来处理的。有以下几种情况。

2.1 Multiple asynchronous request serial(多个异步请求串行)

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

The return result of the previous asynchronous request will be used as the request parameter of the next asynchronous request, so once the previous request is abnormal, the subsequent requests will be abnormal, so try-catch processing needs to be added.

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

2.2 Handling the loading status of asynchronous requests(处理异步请求的加载状态)

loading.value = truevalue = true
try {
  const list = await getList(params)
} finally {
  loading.value = false
}

Generally, before we process an asynchronous request, we will add a loading state to it, and once the request exception occurs, if we do not add a try-catch, the page will always be in the loading state. Therefore, it is necessary to set the loading status to false finally, and it needs to be processed externally when processing in catch.

So, how do we gracefully handle try-catch in asynchronous requests?

一般来说,在处理异步请求之前,我们会为其添加一个加载状态,一旦发生请求异常,如果不添加 try-catch,页面就会一直处于加载状态。因此,有必要将加载状态最终设置为 false,并且在 catch 中处理时需要从外部进行处理。

那么,如何在异步请求中优雅地处理 try-catch 呢?

3. Handling Promises(处理承诺)

First of all, it needs to be clear: Under normal circumstances, the await command is followed by a Promise object. So it can use .catch itself to catch exceptions. Like the second operation above that only handles the loading state, it can be processed in .catch, and then use if judgment to control early exit. There is no need to write try-catch redundant code.

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

loading.value = truevalue = true
let res = await getList().catch(() => (loading.value = false))
if (!res) return

await-to-jshandler function

We can use the above method for simple asynchronous requests, but when encountering multiple asynchronous operations, we need to use the await-to-jslibrary we are going to talk about today. Its introduction is very simple: It can be easily executed without try-catch Handle errors.

And the source code is simple, only 23 lines of code, let’s take a look together.

/**
 * @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

The general process is as follows: The function to accepts the parameters Promise and errorExt. If the Promise is successful, it returns [null, data]. If it is abnormal, it will judge whether it has the errorExt parameter (representing the additional information passed to the err object). If it is sometimes merged with the err captured by the catch Return, or [err, undefined]if none.

一般过程如下: 函数接受 Promise 和 errorExt````参数。如果 Promise 成功,则返回 [null,data]。如果异常,它会判断是否有 errorExt 参数(代表传递给 err 对象的附加信息)。如果有,有时会与 catch Return 捕捉到的 err 合并,如果没有,则返回 ``[err,undefined]

4. How to use(如何使用)

4.1 Install(安装)

# use npm
npm i await-to-js --save
# use yarn
yarn add await-to-js

4.2 Use(使用)

First, introduce the to function, you can see that the package is very small, only 370b, and only 242b after gzip compression, so feel free to import it, don’t worry about the package size.

首先介绍一下 to 功能,你可以看到软件包非常小,只有 370b,经过 gzip 压缩后也只有 242b,所以你可以随意导入,不用担心软件包大小的问题。

1

We use to rewrite the first question above:

我们可以用它来改写上面的第一个问题:

import to from 'await-to-js'

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

After the transformation of the to function, if the first parameter returned is not empty, it means that the request reported an error, and it can be returned in advance. If there is no first parameter, the asynchronous request is successful.

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

【参考文献】

文章:Stop Using try-catch to Catch Async/Await Exceptions

作者:omgzui

日期:5月15日

上述译文仅供参考,原文请查看下面链接,解释权归原作者所有

⚠️:文章翻译如有语法不准确或者内容纰漏,欢迎评论区指正。

【关于TalkX】

TalkX是一款基于GPT实现的IDE智能开发插件,专注于编程领域,是开发者在日常编码中提高编码效率及质量的辅助工具,TalkX常用的功能包括但不限于:解释代码、中英翻译、性能检查、安全检查、样式检查、优化并改进、提高可读性、清理代码、生成测试用例等。

TalkX建立了全球加速网络,不需要考虑网络环境,响应速度快,界面效果和交互体验更流畅。并为用户提供了OpenAI的密钥,不需要ApiKey,不需要自备账号,不需要魔法。

TalkX产品支持:JetBrains (包括 IntelliJ IDEA、PyCharm、WebStorm、Android Studio)、HBuilder、VS Code、Goland.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值