Promise的错误处理及axios的联合使用

519 阅读3分钟

前言

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的高频场景一定离不开数据请求,当axiospromise结合之后我们又应该如何进行错误处理呢? 如何应对多请求下的数据接收与错误处理。

 // 经典设计 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结合使用的两种不同封装方式。如果看完之后对你有帮助请麻烦点个赞 谢谢!