Axios request to cancel – code interpretation

# introduction

In a common scenario where the search box listens for the user to enter change request data, normally we request the server for every change. Generally, the front end uses debounce and the user stops XXX ms before sending the request. However, in some extreme cases, the data of the last request does not respond, and the user changes the input again to initiate a new request. The new request responds first, while the old request responds slowly. The user displays incorrect data.

Axios Solutions

// Before each request abort the previous request
function abort() {
  if (this.source) {
    this.source.cancel(CANCEL_MESSAGE);
    this.source = null; }}function fetchRecords() {
  this.abort();
  this.source = axios.CancelToken.source();
  $http.post('url', params, { cancelToken: this.source.token })
    .then(data= > {
      this.source = null;
    })
    .catch(e= > {
      if(! axios.isCancel(e)) {this.source = null; }}); }// CancelToken another use of CancelToken
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12313', {
  cancelToken: new CancelToken(function executor(c) { cancel = c; })});// Cancel the request
cancel();

Copy the code

Axios requests that the requirements analysis be cancelled

Axios does this by encapsulating const XHR = new XMLHttpRequest(); Xhr.send (), which can be cancelled via xhr.abort(). From the way we used it last time, we need to implement

  1. Add a CancelToken object on Axios
  2. The CancelToken object has the source method on it. The source method returns the token attribute and the Cancel method
  3. Constructor of CancelToken, which can pass a callback function and assign the cancel method.
  4. Add the isCancel method on axios

class CancelToken {
  constructor(executor) {
    executor((msg) = > {
      this.cancel(msg)
    });
  }
  cancel(msg) {
    this.cancelMsg = msg;
  }
  //  
  static source() {
    return {
      token: null.cancel: this.cancel
    }
  }
}

// Key point: cancel the request asynchronously,cancelToken adds a promise
// xhr.js
const { / *... * / cancelToken } = config

if (cancelToken) {
  cancelToken.promise.then(reason= > {
    request.abort()
    reject(reason)
  })
}

// cancelToken.js
class CancelToken {
  constructor(executor) {
    executor((msg) = > {
      this.cancel(msg)
    });
    this.promise = new Promise(resolve= > {
      this.resolvePromise = resolve; })}cancel(msg) {
    // This triggers xhr.js request. Abort
    this.resolvePromise(msg);
    this.cancelMsg = msg;
  }
  //  
  static source() {
    let cancel = null; // ** static method, cannot use this.cancel**

    return {
      // Remember that this token is assigned to cancelToken
      token: new CancelToken((c) = > {
        cancel = c
      }),
      cancel,
    }
  }
}


// There is one last isCancel requirement left

Reject (reason) is used in xhr.js
// Axios.iscancel (reason) reason is the same reference
class Cancel(a){ message? : stringconstructor(message? : string) {
    this.message = message
  }
}

function isCancel(reason) {
  return reason instanceof Cancel
}

// cancelToken.js
class CancelToken {
  constructor(executor) {
    executor((msg) = > {
      this.cancel(msg)
    });
    this.promise = new Promise(resolve= > {
      this.resolvePromise = resolve; })}cancel(msg) {
    IsCancel is achieved by passing new Cancel(MSG)
    this.resolvePromise(new Cancel(msg));
  }
  static source() {
    return {
      token: new CancelToken(() = > {}),
      cancel: this.cancel
    }
  }
}


Axios.isCancel

Copy the code

Note: You can cancel multiple requests using the same Cancel token

// cancelToken.js
class CancelToken {
  constructor(executor) {
    executor((msg) = > {
      this.cancel(msg)
    });
    this.promise = new Promise(resolve= > {
      this.resolvePromise = resolve; })}cancel(msg) {
    CancelToken cancelToken cancelToken cancelToken cancelToken cancelToken cancelToken
    this.reason = new Cancel(msg);
    this.resolvePromise(this.reason);
    
  }
  static source() {
    return {
      token: new CancelToken(() = > {}),
      cancel: this.cancel
    }
  }
}
Copy the code

conclusion

  1. Before developing features, be sure to analyze requirements and list function points.
  2. The abort call problem is handled asynchronously by passing the promise.
  3. Implement isCancel with Instanceof.