What would we do? Before we understand Axios’s CancelToken, how do we cancel an HTTP request that has already been made?
Of course, we all think of the method abort on the XMLHttpRequest prototype, which is used to terminate the request.
Inside AXIos, however, is a complete request-receive-and-cancel mechanism that relies on promises. As we all know, a promise has only three states: Pending, Resolved and Rejected. A promise itself does not “cancel” or “terminate.” There is no such state, where a promise that has been executed from a pending state can only succeed or fail. So, how do you cancel yourself with the same promise? (In fact, they can not cancel their own, unless packaging magic old bottles of new wine 😈)
So, cancelling the request is a tricky part of the AXIos source code, essentially figuring out how to cancel an already implemented promise itself.
Without further comment, when we control the execution of a promise instance ourselves, we can wrap a layer around the promise to cancel it:
Function wrap(p) {// Let abort; Const rejectPromise = new Promise((resolve, reject) => {abort => reject(args) // This step is critical. CancelToken also borrows from this approach to "cancel elsewhere". P.abort ()}) p = promise.race ([p, rejectPromise]); // use promise.race to abort a promise. Return p} let p = wrap(new Promise((resolve, reject) => {setTimeout(() => {resolve(1)}, 3000) })) p.then(res => { console.log('res', res) }, e => { console.log('e,', E)}) setTimeout(() => {p.abort(123) // If the above asynchronous request exceeds 2 seconds, abort is the first to "cancel" the promise}, 2000)Copy the code
Understanding the above code that cancels a promise, especially assigning ABORT to a promise to be called at a later time, is helpful. One key point: It’s up to you whether promises succeed or fail. You don’t necessarily want to write a New Promise and then call a success or failure method as you would normally do. If you don’t want to call resolve or Reject right away, expose resolve or Reject and call it when appropriate.
Source code including comments a total of more than 50 lines, a little around, (knock on the blackboard to remind yourself and small partners!!) The trick is to deal with exposing resolve and reject so that at some point you can do a “cancel action” that affects the state of the promise now being implemented:
function Cancel(message) { this.message = message; } function CancelToken(executor) {if (typeof executor! == 'function') { throw new TypeError('executor must be a function.'); } var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } token.reason = new Cancel(message); resolvePromise(token.reason); Token. reason is passed to the success function in the next then}); } CancelToken.prototype.throwIfRequested = function throwIfRequested() { if (this.reason) { throw this.reason; }}; CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { cancel = c; // Key code 3: implement "cancel the request elsewhere", same as "terminate a Promise" above. }); return { token: token, cancel: cancel }; }; module.exports = CancelToken;Copy the code
Given the source code above, how do we cancel requests already made in AXIos? For example, when switching pages, the original page if there is not received back request, in fact, you can not need. For example, modify the official get request:
var CancelToken = axios.CancelToken; Var {token, cancel} = canceltoken.source (); var {token, cancel} = CancelToken. // The CancelToken constructor has a static method source. Calling it returns an object containing the token and cancel attributes axios.get('/get/server', {CancelToken: CancelToken: cancelToken cancelToken: cancelToken: cancelToken: cancelToken: cancelToken // This token is actually a promise. Within AIxOS, the then method of the token's promise is executed when the request is made, but its current state is still pending and depends on the cancel () method to make it successful. // Then successfully executes, which then calls abort on the XMLHttpRequest prototype to cancel the HTTP request. }) .then(function (response) { // ... }) .catch(function (err) { document.getElementById('people').innerHTML = '<li class="text-danger">' + err.message + '</li>'; }); cancel('Oops! Error happens! Look here! '); // Axios cancels the key step of the request. After executing it, the config config cancelToken will take effect and the token promise will succeed then.Copy the code
For the “cancel request” code above, the page displays the argument to the cancel function and the message passed to cancel the request:
Cancel request: “Perform cancel to make token promise successful”