前言
promise
的出现解决了回调地狱和回调函数控制反转的问题,其他各类工具框架也基于它进行了升级。但是也带来了一些其他问题,比如错误处理就是其中的代表性问题。
常见的错误处理场景
以下示例决断了大部分的promise
错误处理,当使用promise
时请尽量使用promise
本身提供的错误处理方式,如非特殊业务场景请不要使用捕获(addEventListener)、try catch
等措施避免未知bug或监听不到位。
// promise.then
const p1 = new Promise((resolve, reject) => {
// resolve 决议成功
reject("出错了"); // 决议失败
})
// then 接收的第二个参数是调用 reject 的处理函数,也就是错误处理函数。
p1.then(
success => console.log("p1 success", success),
err => console.log("p1 err", err)
)
// promise.catch
p1.catch(err => {
console.log("p1 catch", err)
})
const p2 = new Promise((resolve, reject) => {
// resolve 决议成功
reject("再次错误"); // 决议失败
})
// 多个promise处理
Promise.all([p1, p2]).catch(err => { // all 的问题是只要有一个值错误,则会直接进入catch回调
console.log("promise all", err)
})
// Promise.allSettled 处理一组promise,等待所有决议完成,无论成功或者失败。
const allSettled = Promise.allSettled([p1, p2]);
allSettled.then(results => {
console.log("promise allSettleds", results) // [{status: 'rejected', reason: '出错了'}, {status: 'rejected', reason: '再次错误'}]
})
promise axios async await 的结合
在前端开发中使用promise
的高频场景一定离不开数据请求,当axios
和promise
结合之后我们又应该如何进行错误处理呢? 如何应对多请求下的数据接收与错误处理。
// 经典设计 first error [err, data]
// 创建axios实例
const axiosInstance = axios.create({baseURL: "", timeout: ""});
// 请求拦截
axiosInstance.interceptors.response.use(
res => {
return [null, res.data]
}, // 成功代码
err => { // 请求失败拦截
const { response: { data }, message } = err;
if (data.code === 401) // 错误处理 根据code不同定义你的错误处理方式
// 错误处理完毕后 返回数据到页面
return [err, data.data]
}
)
export default axiosInstance;
// 业务逻辑 单个
const getTableList = async function(){
const [err, list] = await axiosInstance.post(url, payload, config);
if (!err) {
// 请求成功 处理 list相关逻辑
} else {
// 请求错误处理
}
}
// 业务逻辑 多个
const [p1Arr, p2Arr] = await Promise.all(getTableList, getCityList); // 因为拦截器中没有使用 promise.reject 所以这里的逻辑都会执行
const [err1, data1] = p1Arr;
const [err2, data2] = p2Arr;
if (!err1) {} else {};
if (!err2) {} else {};
// 使用 first error 时业务逻辑复杂的情况下,反而会觉得更加难以维护,会定义特别多的逻辑处理代码,无用且繁复。
// 个人更加推荐分离设计,也就是错误处理和业务处理分开(分层处理),灵感来自于TCP/IP模型。
// 在 axiosInstance 中,成功 return data.data,错误 return undefined。
// 错误处理则通过 data.code 进行包装, 定义一个处理函数 errBatch(data) 进行管理即可。
// 如果请求成功 tablist & citylist 是正常的数据
// 如果请求失败 tablist & citylist 返回undefined,通过默认赋值定义为空数组,页面逻辑正常执行。 错误信息则会在拦截器中统一处理
const [tablist = [], citylist = []] = await Promise.all(getTableList, getCityList);
this.tablist = tablelist;
this.citylist = citylist;
// 通过上述两段不同设计的代码可以发现 分层之后的业务逻辑变得清晰明了
结语
以上示例代码完整的演示了promise
中大部分的错误处理方式,并且对比了单多请求业务逻辑下与axios
结合使用的两种不同封装方式。如果看完之后对你有帮助请麻烦点个赞 谢谢!