为什么写这个题目呢?
因为之前写的一个 Node 程序有点小问题,使用的 axios 通过代理请求数据,代理服务器(阿布云)时不时抽风(407、413、503)。
因为第一次写的时候当做一个 DEMO 去实现的,写的挺简陋,只能说大体功能对,但是没有容错机制。
这里我们先算一笔帐啊,一次请求等于 1+100 次,因为我内部还会请求好多数据。
如果只是第一次失败了,那么无关紧要,大不了重发一次。
但是如果是后面 100 次中有极个别暴雷了,那么就会导致整个101次请求全部作废。(因为返回的数据是错误的,使用者会触发第二次请求。不止加重了服务器的压力,还增加了使用者检查的压力)
好了,为什么实现这个功能说了,那么我们要开始实现了。
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 如果失败了我们先判断次数,然后根据具体的错误,进行重试。
ECONNABORTED
很奇怪好好的资源他也不加载就卡住了,所以我设置了 timeoutECONNRESET
也是一个很奇怪的错误。(既然是 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) }) }) }
欢迎大家关注我的公众号。有疑问也可以加我的微信前端交流群。