preface
There are numerous articles and materials on Axios cancellation requests. Most of them are separately introduced to cancel the unfinished request of the previous page or cancel the repeated request when switching routes, and most of them are introduced to the core content, lacking the description of a complete set of schemes.
This article describes a complete solution for switching routes to de-specify and de-duplicate requests, along with some other small dry goods processing
Request to intercept
About axios cancel request, the official document also has a simple description of the use method, I will not repeat the basic method here, directly write the scheme.
Ideas:
A variable is used to store requests that are currently in a pending state, indicated by an identifier. Intercept requests, judge whether there have been still in the pending before the API request of similar, namely the existence of the above variables, if present, cancel the processing, is not normal to send, there’s a request, such as delete the API request after identified in the above variables, it is a complete process of dealing with the cancel the repeat request.
For switched routes (pages), in order to cancel the requests that are still pending on the previous page, it is necessary to listen to the route switching, and judge the request identifiers stored in the above variables each time the switching, which are the requests to be cancelled, just cancel them. Not all pending requests are cancelled, because some requests in the system need not be cancelled due to route switching, such as some global requests. Of course, this can be extended to specify what needs to be cancelled for your actual project.
Regarding the request effect Settings, I am used to a separate file http.js, code comments written step by step is very clear, you read the natural very easy to understand.
// http.js
import axios from 'axios';
// Used to store the status of pending requests
let pendingRequest = [];
/** * @param config - Request configuration item */
const handleRequestIntercept = config= > {
// The method name + the request path
// If there are multiple requests for different baseurLs in a project
${config.method} ${config.baseURL}${config.url}
const requestMark = `${config.method} ${config.url}`;
PendingRequest = pendingRequest = pendingRequest = pendingRequest
const markIndex = pendingRequest.findIndex(item= > {
return item.name === requestMark;
});
// Exist, that is, repeat
if (markIndex > - 1) {
// Cancel the previous duplicate request
pendingRequest[markIndex].cancel();
// Delete the request identifier in pendingRequest
pendingRequest.splice(markIndex, 1);
}
// (re) create a cancelToken for axios for this request
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
config.cancelToken = source.token;
// Set up a custom configuration requestMark item, which is mainly used in response interception
config.requestMark = requestMark;
// Record the identity of this request
pendingRequest.push({
name: requestMark,
cancel: source.cancel,
routeChangeCancel: config.routeChangeCancel // There may be a routeChangeCancel item with a higher priority than the default
});
return config;
};
/** * Response interception processing * @param config - request configuration item */
const handleResponseIntercept = config= > {
// Find the pendingRequest identifier based on the requestMark configuration set in request interception
const markIndex = pendingRequest.findIndex(item= > {
return item.name === config.requestMark;
});
// Delete the flag
markIndex > - 1 && pendingRequest.splice(markIndex, 1);
}
/** * create an axios instance * @param {String} url - access the main url of the background */
const createAxiosInstance = (baseUrl) = > {
let instance = axios.create({
baseURL: baseUrl
});
// By default, the pending request is cancelled if the request is considered to be switched. False: the pending request is not cancelled
instance.defaults.routeChangeCancel = true;
// Request interception
instance.interceptors.request.use(handleRequestIntercept, error => Promise.reject(error));
// Response interception
instance.interceptors.response.use(res= > {
handleResponseIntercept(res.config);
// More often you get res.data
// Return res.data;
return res;
}, error => {
let errorFormat = {};
const response = error.response;
// The request has been sent, but the status code of the server response is outside the 2xx range
if (response) {
handleResponseIntercept(response.config);
// Set the format of the returned error object (according to your actual project requirements)
errorFormat = {
status: response.status,
data: response.data
};
}
// If the request is cancelled, mark it
if (axios.isCancel(error)) {
errorFormat.selfCancel = true;
}
// There is another case
Error. Message is the error message when setting a request that raises an error
// But I think this is usually a script error, our project prompt should not prompt the script error to the user, usually we customize some default error message, such as "created successfully!"
// So there is no processing for this case.
return Promise.reject(errorFormat);
});
// There are some other axios instance Settings you want
// ...
return instance;
}
// Other configurations
// ...
export {
pendingRequest
}
Copy the code
The pending request is cancelled when the route is switched. The pending request is cancelled when the route is switched.
In the routing Settings file, use vue-router as an example
// router.js
import { pendingRequest } from 'http.js';
/ /... This is the other configuration
router.beforeEach((to, from, next) = > {
// Cancel requests that have not finished on the previous page
pendingRequest.forEach(item= > {
item.routeChangeCancel && item.cancel();
});
/ /... Other processing
});
Copy the code
Actual project application
Processing error
Above we decided how to do interception, how to deal with route switching, basically already dealt with.
A few more minor points, remember that we did a test for the response intercept to determine if it was an active cancel, and then set the selfCancel flag.
What’s the use of this? It is used to handle error messages when we make requests in the project. Such as
// I created an axios instance and tied it to Vue's HTTP
Vue.http.get('/api/test').then(res= > {
// Successful request processing
}).catch(e= > {
// If the request is unsolicited, the request is cancelled
e.selfCancel || this.$message.error('Request failed! ');
})
Copy the code
This.$message.error here is mainly used to prompt the error message to the user. Since we cancel the request initiatively, we will go into the catch process, but this is not an error in the actual sense, so we should not tell the user that there is an error.
Therefore, this selfCancel mark is used to tell the developer that this is an error caused by our initiative to cancel the request, and the user should not be prompted to see it
Distinguish whether a page is requested
We used the request config.routeChangeCancel above to determine whether to cancel pending requests when switching routes.
The default routeChangeCancel is set to true when we create an axios instance. When we switch routes, we usually want to cancel the unfinished requests on the last page, so as to avoid the problems such as script errors reported if there are changes or methods or DOM objects related to the last page when the callback function processing is completed due to the switch of routes. Of course, this is also a performance optimization process to improve the user interaction experience, so this is necessary.
Some people might think, just switch the route and cancel all the pending requests. However, there may be some public requests on your system that are not and should not be affected by page switching, and such requests should not be cancelled when switching routes! A common example is that some information in the header of the system needs to be requested. Switching the header of the page does not change, right?
So we have been through the instance. The defaults. RouteChangeCancel = true set, then how to set the request to know which don’t need to cancel switch routing?
Vue.http.get('/api/test', {
routeChangeCancel: false
})
Copy the code
This is overridden when the instance sends the request
In fact, if you don’t want to differentiate in this way, you can actually create two axios instances, one indicating that switching routes should be cancelled, and one that doesn’t need to be cancelled. But IN my opinion, this kind of request that does not need to cancel is less in a project, in a system, in fact, it is more flexible through the form of this configuration, and it is not a lot of trouble to deal with.
conclusion
So much for the cancellation scenario.
Please do not reprint without permission
It starts in front of K