【async/await】异常处理

532 阅读1分钟

问题

在项目中使用 二次封装axios 的 request 函数,当发生异常时(https状态码非200),进行了捕获,并返回 reject(e),而 await 只能接收 resolve() 的返回,所以会阻塞 await 下面的代码执行,比如 无法关闭 loading

解决

方案一

在 await 后面的请求函数添加 .catch(e => ())

const result = await getList().catch(e => {  console.log(e) })
// TODO: 关闭 loading
if (result) {
// do something
}

方案二

使用 try...catch...finally 包裹

try {
  const result = await getList()
  if (result) {
  // do something
  }
} catch (e) {
  console.log(e)
} finally {
  // TODO: 关闭 loading
}

方案三

  1. 安装 await-to-js / 或者直接复制 to 函数到 utils中
  2. 引入 to 函数
  3. 使用 to 函数包裹 await 后面的 promise
import { to } from 'await-to-js'

...
const [err, result] = await to(getList(arg))
// TODO: 关闭 loading
if (result) { 
  // do something 
}

方案四

统一在 request 中使用 try...catch

...
function addTryWrapper(fn) {
  return async function (...args) {
    try {
      const res = await fn.apply(this, args)
      if (res) {
        return res
      }
    } catch (e) {
      console.error('接口请求发生错误:', e)
    }
  }
}

const request = addTryWrapper(api.http.request)
...

利用了装饰器的思路,增加 try..catch 。 只有在正常的时候才会return res, 其他情况都是 return undefined。 这又是一个 async 函数,所以相当于Promise.resolve(res) 或者 Promise.resolve(undefined)

...
const result = await request()
// TODO: 关闭 loading
if (result) { 
  // do something 
}
...

总结

  1. 前三个方法都需要在使用 await 的时候处理,比较麻烦

  2. 在请求接口时,推荐使用方案四,可在 await 下方直接关闭loading。需要注意的是与方案一、方案三一样,方案四在使用 result 的时候,都必须进行判断是否有值再进行后续操作

  3. 如果 await 后面跟着是普通的 promise, 推荐使用方案三。