JavaScript 如何优雅的处理 async/await 异常

Async/await 是 ES7 中的新特性,它可以让开发者编写异步代码像同步代码一样

的确它给我们带来了很多方便的地方,但是在Async/await 中如何来处理错误呢?
在异步的调用中,会产生各种不同的错误,例如:HTTP 请求产生了错误、访问 DB 产生的异常、操作文件产生异常。在 Promise 的使用中,当承诺遇到了错误,它会抛出一个异常,该异常将被捕获到一个方法回调中。在 Async/await 中,我们又如何处理呢,当然很多人会回答:使用 try/catch 来捕获这些错误,这样一来代码会看起来像这样:

async function asyncFunc() {
  try {
    const product = await Api.product({ id: 10 }); if (!product) {
      console.log('No product found')
    }
  } catch (err) {
    console.log(err)

  } try {
    const saveProduct = await Api.save({
      id: product.id, name: product.name
    })
  } catch (err) {
    console.log(err)
  }
}

回顾上面的代码,try/catch 的确可以来解决错误异常的处理,但是让代码非常的不干净,原本 Async/await 的优势就是让代码更佳的简约,这样一来又违背了它的初中,这让我们进入了新的思考。

Go-lang 的灵感

在 Go 语言中处理异常的方式是这样的:

f, err := os.Open("filename.txt")if err != nil { return err }

它看起来要比繁多的 try/catch 更佳的干净,并且让代码更佳容易阅读。我们是不是可以把这种语法运用到 Async/await 中去呢,但是让人失望的是Async/await 如果产生了错误会立即退出你的函数,除非用 try/catch,否则你无法控制它。

但是没有我们聪明的工程师无法办到的事情,Dima 和他的小伙伴利用 Promise 来解决了这个问题:

export default function to(promise) {
  return promise.then(data => {
    return [null, data]
  })
    .catch(err => [err])
}

这一个工具方法接收一个承诺,让后将异步获取到的数据作为返回数组的第二个值,捕捉到的错误作为返回数组第一个值。然后我们的异步代码会变成这样:

async function asyncFunc() {
  let err, product, saveProduct;

  [err, product] = await to(Api.product({ id: 10 })); if (!product) {
    console.log('No product found')
  }

  [err, saveProduct] = await to(Api.save({
    id: product.id, name: product.name
  })); if (err) {
    console.log(err)
  }
}

由此一来,Async/await 又回到了最初的简洁。

await-to-js

最后给 await-to-js 点一个赞,它很好的将这一工具封装成了模块,你可以通过 npm 来安装它,源码地址:https://github.com/scopsy/await-to-js ,代码其实很少,用 Typescript 写的,小功能大作用。

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
export function to<T, U = any>(
  promise: Promise<T>,
  errorExt?: object
): Promise<[U | null, T | undefined]> {
  return promise
    .then < [null, T] > ((data: T) => [null, data])
      .catch < [U, undefined] > (err => {
        if (errorExt) {
          Object.assign(err, errorExt)
        } return [err, undefined]
      })
}

export default to

作者:一俢

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值