Since using Vue2, we have used axios plug-in to call API, if the server or network is unstable and switched, how do you deal with it? Let me share with you my experience.
The specific reason
Recently, the company is working ona project. The server data interface uses THE API output from Php. Sometimes, it fails in the invocation process and shows Provisional Headers are shown in Google Browser.
According to the search engine to come out of the solution, can not solve my problem.
Recently in the research of AOP this concept of development programming, the axios development specification mentioned in the column Interceptors should be this mechanism, reduce the code coupling degree, improve the program reusability, and improve the efficiency of development.
Solution one with pits
In my limited experience, the only thing I can do is make a new request after the AXIos request times out. By studying the instructions for Axios, give it a timeout = 6000
axios.defaults.timeout = 6000;
Copy the code
Then add a column interceptor.
// 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);
});
Copy the code
The purpose of this column interceptor is if after the request has timed out, the column interceptor can capture the information and then proceed to the next step, that is, I want to request again.
Here is the relevant page data request.
this.$axios.get(url, {params: {load:'noload'}}).then(function (response) {
//dosomething();
}).catch(error= > {
// Catch error messages here after timeout.
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) {// I hereby renew my request}}else {
console.log('Error', error.message);
}
console.log(error.config);
});
Copy the code
After the timeout, Uncaught (in Promise) Error: timeout of XXX MS exceeded is displayed.
In catch, it returns an error. Request error, so the retry function is applied here. The retry function can be implemented after testing.
Look at the top, I have dozens of.vue files for this project, and I would go crazy if I had to set up a timeout re-request function for every page.
There’s a serious bug and the mechanism, is the requested link failure or other causes not normal visit, the mechanism of failure, it will not wait for me to set 6 seconds, and has been in the brush, one second request dozens of times, it is easy to bring down the server, please see below, the function of the twinkling of an eye, it made 146 requests.
Solution two with pits
Studied axios source code, after a timeout, the interceptor there axios. Interceptors. Response captured error messages, and the error. Code = “ECONNABORTED”, the specific links
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;
};
Copy the code
So, my solution to global timeout recapture goes like this.
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
returnaxios.request(originalRequest); }});Copy the code
This method can also make a new request, but there are two problems. One is that it only makes a new request once, and if it times out again, it stops making the request. The second problem is that I do a lot of things after each page that has a data request, such as this.$axios.get(URL).then.
Perfect solution
In the way of AOP programming, WHAT I need is a global function of timeout re-request.I need to work on axios.interceptors, find some solutions from others in axios issue on Github, and finally find a perfect solution, which is the following one.
https://github.com/axios/axios/issues/164#issuecomment-327837467
// Set the global number of requests in main.js, and the interval between requests
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);
});
});
Copy the code
The dozens of other.vue pages have this.$axios get and post methods that don’t need to be modified at all.
In the process, thank jooger gives a lot of technical support, this is his personal information, https://github.com/jo0ger, thank you.
Here’s an experiment I did. The axios. Defaults. RetryDelay = 500, request to www.facebook.com
If you have better suggestions, please let me know, thanks.
Making the source code