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

3次阅读

共计 3540 个字符,预计需要花费 9 分钟才能阅读完成。

自从应用 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

正文完
 0