Why do we need to cancel?
We have a common business scene, the user clicks a data submission, users frequently switching a large quantity of data table, in poor network environment, there will be some abnormal situation, of course, all kinds of UI library provide loading condition can help us to solve the above problems, and can be solved by being part of the problem, but we today from another aspect, CancelToken cancels the last repeated request using Axios cancelToken.
How do we cancel?
Take a look at the cancelToken code in the official AIxOS documentation
Method 1: Cancel tokens can be created using the canceltoken. source factory method, like this:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// Processing error}}); axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// Cancel the request (the message argument is optional)
source.cancel('Operation canceled by the user.');
Copy the code
Method 2: You can also create the Cancel token by passing an executor function to the CancelToken constructor:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// The executor function takes a cancel function as an argumentcancel = c; })});// cancel the request
cancel();
Copy the code
How to use it in our project?
The more common approach in our project is to use interceptors.
Of course, we need to define a map object to store the related values. (Map is a new object for ES6. If you are not familiar with ES6, please read Ruan Yifong’s Introduction to ECMAScript 6
// Store pending requests (handle multiple requests)
const pendingRequest = new Map(a)Copy the code
Second, you need to encapsulate the functions of some helper classes
- GenerateRequestKey generates a unique key for repeated requests
import qs from 'qs'
// Generate a unique key for the request
const generateRequestKey = (config = {}) = > {
// Generate a unique key from the url, method, params, data, which is used to determine whether the request is repeated
// Params is the GET request parameter, data is the POST request parameter
const { url, method, params, data } = config
return [url, method, qs.stringify(params), qs.stringify(data)].join('&')}Copy the code
- AddPendingRequest saves repeated requests to
pendingRequest
In the
// addPendingRequest adds repeated requests to pendingRequest
const addPendingRequest = (config) = > {
const key = generateRequestKey(config)
if(! pendingRequest.has(key)) {// Check whether a key exists in pendingRequest
config.cancelToken = new axios.CancelToken(cancel= > {
pendingRequest.set(key, cancel) // Save key and cancel as key-value pairs}}})Copy the code
- Cancel the duplicate request and set the
pendingRequest
Remove the
// removePendingRequest Cancels duplicate requests
const removePendingRequest = (config) = > {
const key = generateRequestKey(config)
if (pendingRequest.has(key)) { // Check whether a key exists in pendingRequest
const cancelToken = pendingRequest.get(key)
cancelToken(key) // Cancel the previously sent request
pendingRequest.delete(key)Delete the requestKey from the request object}}Copy the code
The complete code
import axios from 'axios'
import qs from 'qs'
// Store pending requests (handle multiple requests)
const pendingRequest = new Map(a)// Generate a unique key for the request
const generateRequestKey = (config = {}) = > {
// Generate a unique key from the url, method, params, data, which is used to determine whether the request is repeated
// Params is the GET request parameter, data is the POST request parameter
const { url, method, params, data } = config
return [url, method, qs.stringify(params), qs.stringify(data)].join('&')}// Add the repeated request to pendingRequest
const addPendingRequest = (config) = > {
const key = generateRequestKey(config)
if(! pendingRequest.has(key)) { config.cancelToken =new axios.CancelToken(cancel= > {
pendingRequest.set(key, cancel)
})
}
}
// Cancel duplicate requests
const removePendingRequest = (config) = > {
const key = generateRequestKey(config)
if (pendingRequest.has(key)) {
const cancelToken = pendingRequest.get(key)
cancelToken(key) // Cancel the previously sent request
pendingRequest.delete(key)Delete the requestKey from the request object}}// Request interceptor
service.interceptors.request.use(
config= > {
// Process repeated requests
removePendingRequest(config)
addPendingRequest(config)
return config
},
error= > {
// Request processing error
return Promise.reject(error)
}
)
// Response interceptor
service.interceptors.response.use(
response= > {
// Remove duplicate requests
removePendingRequest(response.config)
return res
},
error= > {
// Exception console for troubleshooting
console.log('error', error)
// Remove duplicate requests
removePendingRequest(error.config || {})
return Promise.reject(error)
}
)
Copy the code
Third, the end
If the code needs to be corrected and modified, welcome to comment and leave a message, I will actively reply.