封装 axios 实现自动重试

为何写这个题目呢?
由于以前写的一个 Node 程序有点小问题,使用的 axios 经过代理请求数据,代理服务器(阿布云)时不时抽风(40七、41三、503)。前端

由于第一次写的时候当作一个 DEMO 去实现的,写的挺简陋,只能说大致功能对,可是没有容错机制ios

这里咱们先算一笔账啊,一次请求等于 1+100 次,由于我内部还会请求好多数据。
若是只是第一次失败了,那么可有可无,大不了重发一次。
可是若是是后面 100 次中有极个别暴雷了,那么就会致使整个101次请求所有做废。(由于返回的数据是错误的,使用者会触发第二次请求。不止加剧了服务器的压力,还增长了使用者检查的压力axios

好了,为何实现这个功能说了,那么咱们要开始实现了。服务器

axios 发起请求

axios 发请求仍是很简单的,那么咱们能够直接仿照他来实现一下封装。微信

axios({
    url: 'https://www.lilnong.top/cors/axiosAutoTry',
    params: 'user=sf',
    method: 'get'
})
.then(console.log)
.catch(console.log)

image.png

实现自动重试

我直接在 data 上增长一个 __try_count 用于设置重试次数。并发

由于 Axios 是支持 Promise,因此咱们的方法也支持。
axios 若是成功了咱们也 resolve。
axios 若是失败了咱们先判断次数,而后根据具体的错误,进行重试。cors

  • 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)
        })
    })
}

微信公众号:前端linong

欢迎你们关注个人公众号。有疑问也能够加个人微信前端交流群。
clipboard.pngdom

相关文章
相关标签/搜索