How to cancel Ajax? Do you want to cancel?

Original link: https://ssshooter.com/2022-06-23-cancel-ajax/

Ajax cancel

If you are familiar with xhr , you will know that Ajax can actually cancel the front end actively, using XMLHttpRequest.abort() . Of course, this is not the era of slash and burn. Except for interviews, you may not be able to write xhr by hand. There are two cancellation methods in axios that everyone knows:

The first is the old-fashioned cancelToken:

 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 { // handle error } } ) axios . post ( '/user/12345' , { name : 'new name' , } , { cancelToken : source . token , } ) // cancel the request (the message parameter is optional) source . cancel ( 'Operation canceled by the user.' )

And then there’s the new (not really new) AbortController:

 const controller = new AbortController ( ) axios . get ( '/foo/bar' , { signal : controller . signal , } ) . then ( function ( response ) { //... } ) // cancel the request controller . abort ( )

After cancelToken and signal are passed to axios, XMLHttpRequest.abort() will be called by some mechanism.

 onCanceled = ( cancel ) => { if ( ! request ) { return } reject ( ! cancel || cancel . type ? new CanceledError ( null , config , request ) : cancel ) request . abort ( ) request = null } config . cancelToken && config . cancelToken . subscribe ( onCanceled ) if ( config . signal ) { config . signal . aborted ? onCanceled ( ) : config . signal . addEventListener ( 'abort' , onCanceled ) }

cancelToken uses the publish-subscribe model to notify axios to cancel the request. Although this part is implemented by axios, it originated from a tc39 proposal cancelable promises proposal , but this proposal was abandoned.

AbortController is an interface that can already be used in browsers. As the name suggests, this is a controller dedicated to aborting behavior. The example of mdn also uses an Ajax request, but it is a fetch that is very popular. It can be seen that the practice of axios and fetch is consistent:

 function fetchVideo ( ) { controller = new AbortController ( ) // 新建一个controller const signal = controller . signal fetch ( url , { signal } ) // 在fetch 方法传入signal . then ( function ( response ) { console . log ( 'Download complete' , response ) } ) . catch ( function ( e ) { console . log ( 'Download error: ' + e . message ) } ) } abortBtn . addEventListener ( 'click' , function ( ) { if ( controller ) controller . abort ( ) // 调用controller.abort 取消fetch console . log ( 'Download aborted' ) } )

Other uses of AbortController

Of course, AbortController not only has a function of suspending Ajax, but you can also see two usage examples by viewing the dom specification document :

A more practical example is to cancel the event listener with AbortController:

 dictionary AddEventListenerOptions : EventListenerOptions { boolean passive = false; boolean once = false; AbortSignal signal; };

By passing a signal to AddEventListener and running abort() to cancel event listening , this method is especially useful for anonymous callback functions.

Another example is for aborting promises . This is a relatively concise and self-documenting method… But in fact, it is not necessary to AbortController to achieve this function, as long as you find a way to get the reject of the promise. I think the point of this example is to learn to use signal’s onabort:

 const controller = new AbortController ( ) ; const signal = controller . signal ; startSpinner ( ) ; doAmazingness ( { ... , signal } ) . then ( result => ... ) . catch ( err => { if ( err . name == 'AbortError' ) return ; showUserErrorMessage ( ) ; } ) . then ( ( ) => stopSpinner ( ) ) ; // … controller . abort ( ) ; function doAmazingness ( { signal } ) { return new Promise ( ( resolve , reject ) => { signal . throwIfAborted ( ) ; // Begin doing amazingness, and call resolve(result) when done. // But also, watch for signals: signal . addEventListener ( 'abort' , ( ) => { // Stop doing amazingness, and: reject ( signal . reason ) ; } ) ; } ) ; }

In short, signal is a simple sender, and the function is biased towards canceling an operation. If you don’t want to implement a pubsub object yourself in some case, use this and you’re done.

This is the end of the introduction of AbortController. I wonder if everyone has gradually forgotten the title… Finally, I want to discuss whether it is useful to cancel Ajax?

To cancel or not to cancel, that is the question

In fact, this Ajax cancellation is just the front-end talking to itself, the back-end doesn’t know to abort, the past request still needs to be executed, if the back-end does not have special processing, the back-end is still running hard if you cancel the 10s request .

So does the “optimization” seen in some articles, the so-called “cancel the request, only keep the last one” really makes sense?

Discuss on a case-by-case basis, for requests to modify data such as POST, even if the response is slow each time, the server is already processing it. It is undoubtedly mentally retarded to cancel the previous POST and send another one again.

For GET, and only for some extreme operations, it may have a little effect. For example, if a super long table is obtained, the result is not obtained, and then the user uses search to quickly return a small amount of data and render it, and wait until the super long table is actually returned. Overwriting the searched data, cancel is really effective in this case. There is also the cancellation of download and upload, but it is estimated that it will rarely be used.

Finally, there is a reasonable but in fact useless benefit: after cancel , a request location can be saved . After all, the number of simultaneous requests for a domain name in the browser is limited. In more cases, timeout, which is more common than cancel, is more practical. Hmm…unless there are five or six super slow requests lined up at the same time, the rotation is still relatively fast…

My personal suggestion is that, in the final analysis, this so-called “cancellation” is a special treatment for very special cases. It’s good to know this. There is no need to cancel the entire operation in the interceptor.

refer to

This article is reprinted from: https://ssshooter.com/2022-06-23-cancel-ajax/
This site is for inclusion only, and the copyright belongs to the original author.

Leave a Comment