Toc
  1. 前言
  2. try catch
  3. Go Lang
  4. await-to-js
Toc
0 results found
Utone
优雅处理 async/await 异常
2019/11/13 Code async await

前言

async/await 是 ES7 中的新特性,方便开发者以同步代码书写异步调用,避免回调地狱

但是对于这样的代码,怎样处理异常?

目前从网上查询的解决方法,大致有两种

try catch

try catch 捕获是非常常见捕获同步代码异常的方法,它可以轻松捕捉到async/await 的异常

async function func() {
  // 通过try catch捕获异常调用的异常
  try {
    const data = await Api.get() // 同步写法、异步调用
    if (!data) {
      console.log('no data')
    }
  } catch (err) {
    console.log(err)
  }
}

假如一个 async 声明的函数中有多次的异步调用,那就需要在每一个在每个异步调用的代码块上,都包一层 try catch,注意,是每一个

当然也可以在最外层包一层 try catch,但是这样一旦有异常抛出,异常代码下方代码就不会再执行,会造成代码逻辑上的错误

以上, 这明显就有悖于我们用 async/await 的初衷:使代码更加简洁

Go Lang

从 Go 语言处理异常得到的灵感。 Go 语言在执行一段代码后,会赋值两个变量

一个是正常运行结果,一个是运行时的异常

若异常为 null,就没有错误需要处理

f, err := os.Open("filename.txt")

if err != nil { return err }

await-to-js

async/await实际上是 promise 的语法糖。再从上述 Go 语言处理异常的灵感,得出另一种解决方案

使用一个包装函数,包装函数中执行 Promise 代码

  • 若正常则返回结果,同时返回的 err 对象 为 null

  • 若运行中有异常抛出,用 catch 捕获异常,返回的 err 对象为捕获到的异常

再使用 ES6 的解构赋值,可以非常方便的实现上述思路

/**
 * 优雅捕获async/await异常 (简洁版await-to-js)
 *
 * @param {*} promise
 */
const to = function(promise) {
  return promise.then(data => [null, data]).catch(err => [err, undefined])
}

// 解构赋值
const [data, err] = await to(func())

// err有值,说明有异常
if (err) {
  console.log('func 有异常抛出')
}

推荐使用 scopsy 贡献的 await-to-js npm 包

/**
 * @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 | null, T | undefined]> {
  return promise
    .then<[null, T]>((data: T) => [null, data])
    .catch<[U, undefined]>((err: U) => {
      if (errorExt) {
        Object.assign(err, errorExt)
      }

      return [err, undefined]
    })
}

export default to
打赏
支付宝
微信
本文作者:Utone
版权声明:本文首发于Utone的博客,转载请注明出处!