自从应用Vue2之后,就应用官网举荐的axios的插件来调用API,在应用过程中,如果服务器或者网络不稳固掉包了, 你们该如何解决呢? 上面我给你们分享一下我的经验。
具体起因最近公司在做一个我的项目, 服务端数据接口用的是Php输入的API, 有时候在调用的过程中会失败, 在谷歌浏览器里边显示Provisional headers are shown。
依照搜索引擎给进去的解决方案,解决不了我的问题.最近在钻研AOP这个开发编程的概念,axios开发阐明里边提到的栏截器(axios.Interceptors)应该是这种机制,升高代码耦合度,进步程序的可重用性,同时进步了开发的效率。
带坑的解决方案一
我的教训无限,感觉惟一能做的,就是axios申请超时之后做一个从新申请。通过钻研 axios的应用阐明,给它设置一个timeout = 6000
axios.defaults.timeout = 6000;
而后加一个栏截器.
// Add a request interceptoraxios.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 interceptoraxios.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 timeoutrequest.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