关于前端:axios请求超时设置重新请求的完美解决方法

自从应用Vue2之后,就应用官网举荐的axios的插件来调用API,在应用过程中,如果服务器或者网络不稳固掉包了, 你们该如何解决呢? 上面我给你们分享一下我的经验。

具体起因最近公司在做一个我的项目, 服务端数据接口用的是Php输入的API, 有时候在调用的过程中会失败, 在谷歌浏览器里边显示Provisional headers are shown。

依照搜索引擎给进去的解决方案,解决不了我的问题.最近在钻研AOP这个开发编程的概念,axios开发阐明里边提到的栏截器(axios.Interceptors)应该是这种机制,升高代码耦合度,进步程序的可重用性,同时进步了开发的效率。

带坑的解决方案一

我的教训无限,感觉惟一能做的,就是axios申请超时之后做一个从新申请。通过钻研 axios的应用阐明,给它设置一个timeout = 6000

axios.defaults.timeout =  6000;

而后加一个栏截器.

// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
});

这个栏截器作用是 如果在申请超时之后,栏截器能够捕抓到信息,而后再进行下一步操作,也就是我想要用 从新申请。

这里是相干的页面数据申请。

this.$axios.get(url, {params:{load:'noload'}}).then(function (response) {
    //dosomething();
}).catch(error => {
    //超时之后在这里捕抓错误信息.
    if (error.response) {
        console.log('error.response')
        console.log(error.response);
    } else if (error.request) {
        console.log(error.request)
        console.log('error.request')
        if(error.request.readyState == 4 && error.request.status == 0){
            //我在这里从新申请
        }
    } else {
        console.log('Error', error.message);
    }
    console.log(error.config);
});

超时之后, 报出 Uncaught (in promise) Error: timeout of xxx ms exceeded的谬误。

在 catch那里,它返回的是error.request谬误,所以就在这里做 retry的性能, 通过测试是能够实现从新申请的功性能, 尽管可能实现 超时从新申请的性能,但很麻烦,须要每一个请API的页面里边要设置从新申请。

看下面,我这个我的项目有几十个.vue 文件,如果每个页面都要去设置超时从新申请的性能,那我要疯掉的.而且这个机制还有一个重大的bug,就是被申请的链接生效或其余起因造成无奈失常拜访的时候,这个机制生效了,它不会期待我设定的6秒,而且始终在刷,一秒种申请几十次,很容易就把服务器搞垮了,请看下图, 一眨眼的性能,它就申请了146次。

带坑的解决方案二

钻研了axios的源代码,超时后, 会在拦截器那里 axios.interceptors.response 捕抓到错误信息, 且 error.code = “ECONNABORTED”,具体链接

https://github.com/axios/axios/blob/26b06391f831ef98606ec0ed406d2be1742e9850/lib/adapters/xhr.js#L95-L101

// Handle timeout
request.ontimeout = function handleTimeout() {
  reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED',
    request));
  // Clean up request
  request = null;
};

所以,我的全局超时从新获取的解决方案这样的。

axios.interceptors.response.use(function(response){
....
}, function(error){
    var originalRequest = error.config;
    if(error.code == 'ECONNABORTED' && error.message.indexOf('timeout')!=-1 && !originalRequest._retry){
            originalRequest._retry = true
            return axios.request(originalRequest);
    }
});

这个办法,也能够实现得新申请,但有两个问题,1是它只从新申请1次,如果再超时的话,它就进行了,不会再申请。第2个问题是,我在每个有数据申请的页面那里,做了许多操作,比方 this.$axios.get(url).then之后操作。

实现的解决办法

以AOP编程形式,我须要的是一个 超时从新申请的全局性能, 要在axios.Interceptors下功夫,在github的axios的issue找了他人的一些解决办法,终于找到了一个实现解决方案,就是上面这个。

https://github.com/axios/axios/issues/164#issuecomment-327837467

//在main.js设置全局的申请次数,申请的间隙
axios.defaults.retry = 4;
axios.defaults.retryDelay = 1000;
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
    var config = err.config;
    // If config does not exist or the retry option is not set, reject
    if(!config || !config.retry) return Promise.reject(err);
    // Set the variable for keeping track of the retry count
    config.__retryCount = config.__retryCount || 0;
    // Check if we've maxed out the total number of retries
    if(config.__retryCount >= config.retry) {
        // Reject with the error
        return Promise.reject(err);
    }
    // Increase the retry count
    config.__retryCount += 1;
    // Create new promise to handle exponential backoff
    var backoff = new Promise(function(resolve) {
        setTimeout(function() {
            resolve();
        }, config.retryDelay || 1);
    });
    // Return the promise in which recalls axios to retry the request
    return backoff.then(function() {
        return axios(config);
    });
});

其余的那个几十个.vue页面的 this.$axios的get 和post 的办法基本就不须要去批改它们的代码。

以下是我做的一个试验。。把axios.defaults.retryDelay = 500, 申请 www.facebook.com

依照常规,给出源代码,如有更好的倡议,请通知我,谢谢。
http://github.com/ssttm169/use-axios-well

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据