封装 axios 实现自动重试
为什么写这个题目呢?
因为之前写的一个 Node 程序有点小问题,使用的 axios 通过代理请求数据,代理服务器(阿布云)时不时抽风(407、413、503)。
因为第一次写的时候当做一个 DEMO 去实现的,写的挺简陋,只能说大体功能对,但是没有容错机制。
这里我们先算一笔帐啊,一次请求等于 1+100 次,因为我内部还会请求好多数据。
如果只是第一次失败了,那么无关紧要,大不了重发一次。
但是如果是后面 100 次中有极个别暴雷了,那么就会导致整个101次请求全部作废。(因为返回的数据是错误的,使用者会触发第二次请求。不止加重了服务器的压力,还增加了使用者检查的压力)
好了,为什么实现这个功能说了,那么我们要开始实现了。
axios 发起请求
axios 发请求还是很简单的,那么我们可以直接仿照他来实现一下封装。
axios({
url: 'https://www.lilnong.top/cors/axiosAutoTry',
params: 'user=sf',
method: 'get'
})
.then(console.log)
.catch(console.log)
实现自动重试
我直接在 data 上增加一个 __try_count 用于设置重试次数。
因为 Axios 是支持 Promise,所以我们的方法也支持。
axios 如果成功了我们也 resolve。
axios 如果失败了我们先判断次数,然后根据具体的错误,进行重试。
- 407 就是我理解的抽风
- 413 是请求并发太高,为了不占用多少可以加个延时器。
- 503 也是我理解的抽风
- ECONNABORTED 很奇怪好好的资源他也不加载就卡住了,所以我设置了 timeout
- ECONNRESET 也是一个很奇怪的错误。(既然是 Node,我理解他经常出错误。)
function axiosAutoTry(data){
return new Promise((resolve, reject)=>{
axios(data)
.then((data)=>{
resolve(data)
})
.catch(error=>{
// 有重试次数
if(typeof data.__try_count == 'number' && data.__try_count>0){
console.error('重试请求', error.message, data)
data.__try_count--;
if(error.code == 'ECONNABORTED'){
// 中止,超时
return resolve(axiosAutoTry(data))
}else if(error.code == 'ECONNRESET'){
//
return resolve(axiosAutoTry(data))
}else{
if(error.response && error.response.status == 407){
// 代理407
return setTimeout(v=>{
resolve(axiosAutoTry(data))
}, 500 + Math.random() * 500)
}else if(error.response && error.response.status == 503){
// 服务器异常
return setTimeout(v=>{
resolve(axiosAutoTry(data))
}, 1000 + Math.random() * 500)
}else if(error.response && error.response.status == 429){
// 并发超过限制
return setTimeout(v=>{
resolve(axiosAutoTry(data))
}, 1000 + Math.random() * 1000)
}
// console.error('异常错误', error)
}
}
reject(error)
})
})
}