停止像这样使用 “async/await”,改用原版

内容分享5天前发布
0 8 0

最近我看到一些开发者使用这种方法来处理 async/await 错误。

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
function to(promise, errorExt) {
  return promise
    .then((data) => [null, data])
    .catch((err) => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt);
        return [parsedError, undefined];
      }
      return [err, undefined];
    });
}

async function doSomething() {
  const [error1, result1] = await to(fetch(''));
  if (error1) {
    return;
  }

  const [error2, result2] = await to(fetch(result1));
  if (error2) {
    return;
  }
  // ...
}

正如你所看到的,他们把函数包起来,把原来的Promise转换成一个肯定会成功的 “Promise”,并返回一个数组。

如果原始的Promise成功了,那么数组中的第一项是空的,表明没有错误,第二项是原始 Promise的结果。如果原来的Promise失败了,那么数组的第一项是错误,第二项是未定义。就是这样了。

他们认为这很优雅,使代码更易读。但我不这么认为,我也不提议这样使用它

我认为这样的封装有点过度,在大多数情况下,不需要这样做。接下来,我将从两个角度说明我的观点。

1. 从设计的角度来看

Async/await API的目的是允许开发者像写同步代码一样写异步代码。因此,可以使用try…catch来捕获async/await错误。

而这样的函数似乎为我们思考到了一切,但其他刚看到你的代码的开发者总会有这样的疑问。为什么to函数返回的Promise所使用的await没有用try…catch来包装?

停止像这样使用 "async/await",改用原版

只有找到原始的to函数定义,并理解其意图,你才能知道 “啊,原来to函数返回的 Promise 永远不会被拒绝”。

所以它进一步增加了其他开发者的理解成本,使得熟悉的 async/await 变得不再 “熟悉”。

2. 从实用性的角度来看

to函数的主要使用情况是,在同一上下文中有多个await promises,而它们相应的错误处理方式是不同的。那么就使用这个封装函数对每个错误进行不同的处理,减少对try…catch的使用。

但在实际开发,在每个到函数之后,你需要使用if语句来确定是否有错误。这与使用try…catch的本意没有什么不同,都是为了检查错误。

停止像这样使用 "async/await",改用原版

其次,在真实的生产环境中,下一个Promise依赖上一个Promise的情况并不少见。但重大的一点是,这两个Promise一般是关联函数。所以在外层使用try…catch来统一处理错误是没有问题的。列如说

停止像这样使用 "async/await",改用原版

最后,在JavaScript中,大多数Promise场景都是在 Input/output上,列如网络IO和文件IO。这些IO场景可以将拦截器封装在下层,并根据错误代码统一处理。例如,使用axios拦截器。

停止像这样使用 "async/await",改用原版

所以它可能并不像预期的那样实用。也就是说,它可能只用于整个项目的一小部分,而且成本超过了收益。

这就是我所有的观点,你怎么看?你赞成这种做法吗?

作者:Marina Mosti 译者:前端小智 来源:medium 原文:
https://blog.bitsrc.io/stop-using-async-await-like-this-use-the-original-instead-172b5df17589

© 版权声明

相关文章

8 条评论

您必须登录才能参与评论!
立即登录
  • 头像
    金晓玲 读者

    try catch都是对自己的代码不自信

    无记录
  • 头像
    创强 读者

    前端很少用try catch

    无记录
  • 头像
    阿渊与雪猫 投稿者

    我们都是统一处理服务端的各种异常,所以promise的确永远不会reject,而是resolve一个对象,里面包含success,业务只需判断success即可

    无记录
  • 头像
    女士 读者

    这说的。后端大家都尽可能的不要trycatch,怎么到了前端就尽量写try了?

    无记录
  • 头像
    凌晨不晚ohhh 投稿者

    前端真的太灵活 各种写法 各种骚操作 一步一个坑

    无记录
  • 头像
    简心简行致远 读者

    try catch 搭配 const await 赋值有点不方便,因为try 也是个代码块,在 try 之外用不了 const 变量。为了解决这个往往要在前面用 let 声明变量再赋值或者干脆把所有使用变量的代码包起来。不过我也不推荐用文中那种形式,不规范,而且 throw error 可以跨越多个函数栈,将异常抛给上层处理

    无记录
  • 头像
    娜就是幸福 读者

    智智智,从来不写catch

    无记录
  • 头像
    小叶 读者

    收藏了,感谢分享

    无记录