First of all, we should make it clear that cancelToken is the API used by axios to cancel requests.
Then why cancel it? Because the response time of the browser's request is uncertain, the number of requests is too many, and the requests initiated earlier may respond later. Therefore, in order to improve page performance and reduce unnecessary waiting, we need to cancel earlier requests that do not need to wait.
What kind of excessive requests are meaningless and waste of performance? For example:
(1) Route page Jump of the menu and high-frequency switching of the tab bar;
(2) When the change event of the search box is fuzzy matched, multiple ajax requests are sent in a short time, and the returned data is not the most desired.
Of course, there are many applicable scenarios! What you know can be sent out at the bottom of the comment area for everyone to learn ~
Note: cancel token is not a cancellation in the sense that the request will still be sent to the server, but only processed by the browser.
How to create a cancelToken? Specifically, there are two ways to write it:
The first method: create a canceltoken using the CancelToken.source factory method:
const cancelToken = axios.CancelToken; const source = cancelToken.source(); axios.get('/**/**',{ cancelToken:source.token }).catch(function(thrown)=>{ if(aixos.isCancel(thrown)){ //Cancel the request and print the log }else{ //Processing error } }) source.cancel("cancel")//Cancel request, optional parameters
The second method is to create a canceltoken by passing an executor function to the constructor of canceltoken
const cancelToken = axios.CancelToken; let cancel; axios.post("**/**",{ name:"11" }, { cancelToken:new cancelToken(function executor(c){ //The executor function takes a cancel function as an argument cancel = c; }) }) cancel();//Cancel request
So how do we apply it in the project to cancel duplicate requests?
We can add the current request address to an array in the executor function. Then, at the next request, judge whether the current request exists: if it already exists, cancel it directly.
It should be noted here that only using url as key is not afraid of uniqueness or accuracy; Therefore, we need to use all the information currently requested to generate a unique key.
//Generate a unique key based on the current request information funciton onlyKey = function(config){ const {url,method,params,data} = config; return `${url}${method}${JSON.stringify(params)}${JSON.stringify(data)}` } const pendingList = new Map(); //Add request information to pendingList: function addPending (config){ config.cancelToken = new cancelToken(c=>{ if(!pendingList.has(key)){ pendingList.set(key,c) } }) } //Check whether there are duplicate requests, and delete the duplicate requests if there are const removePending = (config) => { //Generate a unique key based on the current request information if(pendingList.has(key)){ const cancelToken = pendingRequest.get(key); cancelToken(key); pendingRequest.delete(key); } }) }
be careful:
(1) The first request will never be canceled because it has not been added to the pendingList store.
(2) It is best to judge before route jump. If it is not the current route, remove the request waiting for the current pendingList.
After seeing how to apply it in the project, if you are still interested, let's learn about the source code with me!
var Cancel = require('./Cancel'); function CancelToken(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } //Define resolvePromise and create a promise instance; //Assign resolve to resolvePromise; Makes it possible to change the state of the object outside promise var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); //Assign an instance of the current CancelToken to the token var token = this; //Pass in the cancel method, in which the resolvePromise method can be called; To execute the resolve method of promise and change the state executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } token.reason = new Cancel(message); resolvePromise(token.reason); }); } /** * If cancellation is requested, a "Cancel" is thrown. */ CancelToken.prototype.throwIfRequested = function throwIfRequested() { if (this.reason) { throw this.reason; } }; //The returned object contains a new 'CancelToken' and a function that cancels the request when called CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { //c here is the cancel method passed to the executor in the CancelToken cancel = c; }); return { token: token, cancel: cancel }; }; module.exports = CancelToken;
I probably can share these reserves with you about the cancelToken of axios. If you know more and more clearly, welcome to guide in the comment area! I must be taught with an open mind!