axios 之cancelToken原理以及使用

axios 之cancelToken原理以及使用

cancelToken

在真实项目中,当路由已经跳转,而上一页的请求还在pending状态,如果数据量小还好,数据量大时,跳到新页面,旧的请求依旧没有停止,这将会十分损耗性能,这时我们应该先取消掉之前还没有获得相应的请求,再跳转页面。这里axios给我们提供了一个方法:

cancelToken其实就是用来取消ajax请求

基本用法

//切换页面取消请求
let source = axios.CancelToken.source();

axios.interceptors.request.use((request) => {
  request.cancelToken = source.token;
  return request;
});
router.then((lib) => {
  lib.default.beforeEach((to, from, next) => {
    source.cancel();
    source = axios.CancelToken.source();
    next();
  });
})

取消请求之后,会进入error,在里面处理一下如果是取消请求,就不报错,

    axios.interceptors.response.use(
      (response) => {
         return response;
    }, 
      (error) => {
        if (axios.isCancel(error)) {
     
            console.log( 'request cancel ', JSON.stringify(error))
            return new Promise(() =>{})
        }
        return Promise.reject(error)
    })

实现原理

promise只有三种状态,pending(等待),resolved(成功),rejected(失败)。

它的本质就是在解决如何取消一个已经执行的promise本身

源码部分

function Cancel(message) {
  this.message = message; // 可以传递因何取消请求的message
}

function CancelToken(executor) {
  // 判断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;
  // 以上token现在有一个promise属性,是一个未成功的promise对象;
  executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason); //关键代码二: 把接收到的“取消请求信息”token.reason传递给下一个then中成功函数作为参数
  });
}

CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  if (this.reason) {
    throw this.reason;
  }
};
// source 方法
CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c; // 关键代码三:实现“在他处取消请求”,与上面“终止一个promise”异曲同工。
  });
  return {
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;
source()函数

source方法很简单,就是返回一个具有token和cancel属性的对象,但是token和cancel都是通过CancelToken这个构造函数来的,

token

souce.token是一个实例化对象,是一个未成功的promise对象;

cancel()函数

souce.cancel就是用来触发取消请求的函数。

cancel执行,给token加了一个reason属性,

Cancel特别简单就是给实例化对象添加一个message属性,所以现在token.reason是一个具有message属性的对象了。

cancelToken

axios/lib/adapters/xhr.js中一探究竟(这里只截取其中关于cancelToken的部分)。

// 在发送请求之前,验证了cancelToken,看来此处就是用来取消请求的;
if(config.cancelToken){
    // 具体是如何取消的,是在这个判断内定义的;
    config.cancelToken.promise.then(function(cancel){
        request.abort();
        reject(cancel);
        request = null;
    })
}
// 发送请求
request.send(requestData);

axios 之cancelToken原理以及使用的相似文章