“This is the 13th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”
Interviewer: The request has been sent. How do I cancel the request that has been sent?
Interviewer: (a question immediately arises in your mind: can you cancel a request that has already been sent?) This…… This…… I don’t know.
After the interview, search baidu….. immediately
AbortController
The AbortController interface represents a controller object that can terminate one or more Web requests as needed.
-
AbortController() : The AbortController() constructor creates a new AbortController object instance
-
Signal: The signal property returns an AbortSignal object instance, which can be used with/about a Web(network) request
-
Abort () : Terminates an unfinished Web request. It can terminate the FETCH request, any consumer or stream that responds to the Body
Fetch Interrupt request
Fetch is an interface provided by the Web to Fetch resources. If you want to terminate a Fetch request, you can use the AbortController interface provided by the Web.
We first create a controller using the AbortController() constructor, and then use the abortController.signal property to get a reference to its associated AbortSignal object. When a fetch request is initialized, we pass AbortSignal as an option to the request object (as follows: {signal}). This associates the signal and controller with the fetch request and then allows us to abort the request by calling abortController.abort ().
const controller = new AbortController(); let signal = controller.signal; Console. log(' initial state of signal: ', signal); const downloadBtn = document.querySelector('.download'); const abortBtn = document.querySelector('.abort'); downloadBtn.addEventListener('click', fetchVideo); abortBtn.addEventListener('click', function() { controller.abort(); Console. log(' abort status of signal: ', signal); }); function fetchVideo() { //... fetch(url, {signal}).then(function(response) { //... }).catch(function(e) { reports.textContent = 'Download error: ' + e.message; })}Copy the code
When we abort the request, the network request becomes something like this:
AbortSignal AbortSignal AbortSignal AbortSignal AbortSignal
As you can see, the aborted property of the AbortSignal object changes from false to true after the AbortSignal object is aborted.
Run sample online (code from MDN)
AbortControllter has compatibility issues as follows:
Axios interrupts the request
Axions interrupts a request in two ways:
Methods a
Canceltoken.souce Factory method creates a cancel token as follows: canceltoken.souce factory method canceltoken.souce
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('https://mdn.github.io/dom-examples/abort-api/sintel.mp4', { cancelToken: Source.token}). Catch (function (thrown) {// Determine if the request has been aborted if (axios.iscancel (thrown)) {// Parameter thrown is custom information console.log('Request canceled', thrown.message); } else {// handle error}}); // Cancel the request (the message argument is optional) source.cancel('Operation Canceled by the user.');Copy the code
The aborted network request looks like this:
Let’s take a look at the initial and post-suspension souce state:
As you can see, the initial and post-abort source states have not changed. So how do we determine the abort status of a request? Axios provides us with an isCancel() method to determine the abort status of the request. The argument to the isCancel() method is the customized information we need to abort the request.
Way 2
CancelToken creates a cancel token by passing an executor function to the CancelToken constructor: CancelToken
const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: New CancelToken(function executor(c) {// The executor function accepts a cancel function as an argument cancel = c; })}); // Cancel the request cancel('Operation Canceled by the user.');Copy the code
The browser running results are the same as the method 1, and are not described here.
Run sample online (code from MDN)
Umi-request Indicates an interrupt request
Umi-request is based on FETCH encapsulation and has the characteristics of FETCH and AXIOS. The abort request is the same as FETCH and AXIos. Details can be found in the official document
Note that AbortController has problems with polyfill in earlier browsers. Umi-request does not abort requests with AbortController in some versions.
CancelToken is used to abort a request in a UMI project
The default request library in a UMI project is Umi-Request, so we can use the methods provided by UMi-Request to abort requests. In addition, DVA can be used with UMI projects, so the following is a brief introduction to the process of CancelToken cancelling requests in DVA.
1. Write the request function and cancel function in a file in the services directory
import request from '@/utils/request'; const CancelToken = request.CancelToken; let cancel: any; OSS export async function uploadContractFileToOSS(postBody: Blob): Promise<any> { return request(`/fms/ossUpload/financial_sys/contractFile`, { method: "POST", data: PostBody, requestType: 'form', // Pass an executor function to the CancelToken constructor to create a cancel token CancelToken: New CancelToken((c) => {cancel = c})})} // Cancel contract file upload export Async function cancelUploadFile() {return cancel && cancel() }Copy the code
2. Write Effect in Models:
*uploadContractFileToOSS({ payload }: AnyAction, { call, put }: EffectsCommandMap): any { const response = yield call(uploadContractFileToOSS, payload); yield put({ type: 'save', payload: { uploadOSSResult: response? .data, } }) return response? .data }, *cancelUploadFile(_: AnyAction, { call }: EffectsCommandMap): any { const response = yield call(cancelUploadFile) return response },Copy the code
Trigger the corresponding action in the page via the dispatch function:
/ / a request dispatch ({type: 'contract/fetchContractFiles, content: {contractId: ${id} ` `,}}) / / cancellation request dispatch ({type: "contract/cancelUploadFile" })Copy the code
Utils /request.js/utils/request.js/utils/request.js/utils/request.js
const errorHandler = (error: { response: Response }): Response => { const { response } = error; notification.destroy() if (response && response.status) { const errorText = codeMessage[response.status] || response.statusText; const { status, url } = response; Notification. error({message: 'request error ${status}: ${url}', description: errorText,}); } else if (error? .['type'] === 'TypeError') {notification.error({description: 'your network is abnormal, cannot connect to the server ', message:' network is abnormal ',}); } else if (error? .['request']? .['options']? .['cancelToken']) {notification.warn({description: 'current request has been cancelled ', message:' Cancel request ',}); } else if (! Response) {notification.error({description: 'Your network is abnormal, cannot connect to the server ', message:' Network is abnormal ',}); } else {notification.error({description: 'please contact the website developer ', message:' unknown error ',}); } return response; };Copy the code