记一次重试机制和服务器响应慢导致的异常
先说下异常是什么:正常情况下,我们的数据,axios返回后都是在res.data中的,于是项目里面常见的就是来个响应拦截,然后返回res.data。
现在重试机制 + 服务器响应慢,会导致最后返回的数据直接就是res.data里面的内容了,你再.data,自然就有问题了
解决:判断是否是axiosResponse对象,如果是,正常返回res.data,如果不是,直接返回res(现阶段:重试的请求得到的结果和之前超时请求的结果一样的)
过程分析:
1.正常请求
先看下正常请求的日志输出:res是axiosResponse对象
------------------------
request AOP 1692346964543 {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 5000, …}
Response AOP res: {data: {…}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
Response AOP HttpStatus: 200 | JDStatus 200
------------------------
weightVolumeUpload {barCode: 'JD11', code: 200, message: 'OK'}
2.请求超时
再请求一次的时候超时了(服务器响应慢)触发了重试机制
------------------------
request AOP 1692346973680 {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 5000, …}
retry touch: AxiosError {message: 'timeout of 5000ms exceeded', name: 'AxiosError', code: 'ECONNABORTED', config: {…}, request: XMLHttpRequest, …}
retryCount: 1
3.过多响应
然后服务器又很快反应了,还把上次超时的数据也给我返回了。。。
------------------------
request AOP 1692346980593 {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 5000, …}
Response AOP res: {data: {…}, status: 200, statusText: 'OK', headers: AxiosHeaders, config: {…}, …}
Response AOP HttpStatus: 200 | JDStatus 200
------------------------
Response AOP res: {barCode: 'JD11', code: 200, message: 'OK'}
Response AOP HttpStatus: undefined | JDStatus undefined
------------------------
4.响应处理
但是,Ajax的地方,只收到服务器返回的最后一次数据。类型不是axiosResponse的,而是直接就是服务器返回的数据:
weightVolumeUpload {barCode: 'JD11', code: 200, message: 'OK'}
过程如图所示:
axios请求得到的数据一般都会放在res.data里面,响应拦截一般会返回一个res.data,现在我们可能会遇到直接返回data的情况,我是这样暂时处理的:(这两次服务器返回结果其实一样)
每个AxiosResponse对象都会有个res.status属性,服务器端返回的数据没有这个属性名字是code(你后端返回也有个status就不能这么判断,可以通过实例对象判断,也可以通过其他属性判断)
5.附录
// 响应拦截
myAxios.interceptors.response.use(res => {
console.debug("Response AOP res:", res);
console.debug("Response AOP HttpStatus:", res?.status, '| JDStatus', res?.data?.code);
console.debug("------------------------");
// 是AxiosResponse对象才是我要的东西
if (res.hasOwnProperty('status')) { // 这个逻辑你要根据你后端返回微调
return res.data;
} else {
return res; // 返回对象不是AxiosResponse,这个res就相当于是res.data里面的数据了
}
}, error => {
return Promise.reject(error);
})
重试机制:
axiosRetry(myAxios, {
retries: 3, // 重试次数
retryDelay: (retryCount) => {
console.debug('retryCount:', retryCount);
return retryCount * 1000; // 重试时间累加,可以写1500
},
shouldResetTimeout: true, // 每次重试都重置超时时间
// 自定义条件,针对状态为500、1000、超时、网络问题进行重试
retryCondition: (error) => {
console.debug('retry touch:', error);
return error?.response?.status === 500 || // JD服务器内部错误
error?.response?.status === 1000 || // JD服务器内部错误
error?.code === 'ECONNABORTED' || // 后端响应超时☆
error?.code == 'ERR_NETWORK'; // 网络异常
},
});
作者:毒逆天
打赏:18i4JpL6g54yAPAefdtgqwRrZ43YJwAV5z