问题
在项目中使用 二次封装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
}
方案三
- 安装 await-to-js / 或者直接复制 to 函数到 utils中
- 引入 to 函数
- 使用 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
}
...
总结
-
前三个方法都需要在使用 await 的时候处理,比较麻烦
-
在请求接口时,推荐使用方案四,可在 await 下方直接关闭loading。需要注意的是与方案一、方案三一样,方案四在使用 result 的时候,都必须进行判断是否有值再进行后续操作
-
如果 await 后面跟着是普通的 promise, 推荐使用方案三。