[Axios]: what is the principle of the "request cancellation" feature of Axios?

Posted by pklover on Tue, 28 Dec 2021 07:47:03 +0100

1. Background

In dealing with front-end and back-end interactions, Sometimes, it is necessary to carefully consider the request timing of the interface (for example, when the request is sent during frequent Tab switching, tree node switching and data entry) or the processing timing of the data returned by the interface (for example, when the interface has not returned, it is necessary to switch the route. If the route has been switched away, what about the previously requested data?) to avoid some useless requests or differences in the return order of the interface (for example, if the same button is clicked multiple times, what should I do if the later button returns first and the first button returns later?).

Common processing methods are:

  • Add anti shake: control the request timing. For frequent operations, the request is made only at the last action.
  • Lock status: control request timing. Direct prohibition of very frequent operations must be carried out one by one.
  • Cancel request: controls the processing time of the request. Cancel the request that has not been returned before and will no longer be processed.

2. Axios has the "request cancellation" skill

Axios has its own cancel token API, which supports the "request cancellation" skill

// The source factory method of CancelToken, and the constructed object contains:
// 1. token: an instance of CancelToken, i.e. token
// 2. cancel: a function used to cancel a token.
const source = axios.CancelToken.source();

axios.get('/user/12345', {
  // Inject the token instance (i.e. CancelToken) into axios
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    // Use isCancel to determine whether the request exception is caused by "request cancellation"
    console.log('Request canceled', thrown.message);
  } else {
     // Exception handling for other types of requests
  }
});

// The cancel function can be called externally to cancel the token;
// axios internally observes that the token is cancelled, and then cancels the request;
source.cancel('Operation canceled by the user.');

3. What is the principle of CancelToken in Axios?

3.1. Where is the source code?

The CancelToken API of Axios is an independent module in the source code.

Let's first look at how CancelToken can be used independently

Then study how it works with Axios

3.2. How to use it?

Usage 1: use the factory to construct the token and is based on the "subscription" API

const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "Cancellation reason:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "Cancellation reason:", reason, isCancel(reason));
}

const {token, cancel} = CancelToken.source();
token.subscribe(handleCancel1); // subscribe
token.subscribe(handleCancel2); // subscribe
token.unsubscribe(handleCancel2) // Unsubscribe

cancel("Test cancel!"); // Cancel token

Usage 2: use the factory to construct the token and is based on the "Promise" API

const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "Cancellation reason:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "Cancellation reason:", reason, isCancel(reason));
}

const {token, cancel} = CancelToken.source();
token.promise.then(handleCancel1); // subscribe
const p = token.promise.then(handleCancel2); // subscribe
p.cancel(); // Unsubscribe

cancel("Test cancel!"); // Cancel token

Usage 3: do not use factory to construct token

const CancelToken = require("./CancelToken");
const isCancel = require("./isCancel");

function handleCancel1(reason){
    console.log("handleCancel1", "Cancellation reason:", reason, isCancel(reason));
}
function handleCancel2(reason){
    console.log("handleCancel2", "Cancellation reason:", reason, isCancel(reason));
}

let cancel;
const token = new CancelToken((c)=>{
    cancel = c;
});
token.subscribe(handleCancel1); // subscribe
token.subscribe(handleCancel2); // subscribe
token.unsubscribe(handleCancel2) // Unsubscribe

cancel("Test cancel!"); // Cancel token

Note: events subscribed on cancelled tokens will be triggered immediately.

const CancelToken = require("./CancelToken");

const {token, cancel} = CancelToken.source();
console.log(new Date().toLocaleTimeString(), "[Not cancelled]:subscribe(Cancel event 1); And will cancel in 5 seconds;");
token.subscribe((reason)=>{
    console.log(new Date().toLocaleTimeString(), "[Cancelled]:trigger(Cancel event 1)(Cancellation reason:"+reason+"); And will be in 5 seconds, On the premise of cancellation, subscribe(Cancel event 2);");
    setTimeout(()=>{
        console.log(new Date().toLocaleTimeString(), "[Cancelled]:subscribe(Cancel event 2);");
        token.subscribe((reason)=>{
            console.log(new Date().toLocaleTimeString(), "[Cancelled]:trigger(Cancel event 2);");
        });
    }, 5000)
});

setTimeout(()=>{
    console.log(new Date().toLocaleTimeString(), "[Not cancelled]:cancel(Reason for cancellation: Test cancellation)");
    cancel("Test cancel!");
}, 5000)

3.3. Principle analysis (CancelToken.js)

4. How does Axios integrate with CancelToken?

By analyzing the principle of CancelToken,

After Axios receives the external incoming CancelToken token object,

You only need to subscribe to the cancellation event of the token,

When the cancellation event is triggered, it can be handled accordingly

subscribe:

Unsubscribe:

5. AbortController of Axios and Fetch API?

The AbortController of FetchAPI can be roughly understood as the CancelToken officially provided by W3C.

Axios also provides compatible processing for AbortController:

reference resources:

https://github.com/axios/axios https://axios-http.com/