axios源码解析 - 请求拦截器

axios请求拦截器,也就是在请求发送之前执行自定义的函数。

axios源码版本 - ^0.27.2 (源码是精简版)

平时在业务中会这样去写请求拦截器,代码如下:

// 创建一个新的实例
var service = axios.create();

// 请求拦截器
service.interceptors.request.use((config) => {
  // 请求头加token
  config.headers['token'] = 'xxx';
  ... ... ...
 
  return config;
}, (err) => {
  return Promise.reject(err);
});

 其中 service.interceptors.request.use 方法起到了作用,其核心源码如下:

/* axios/lib/core/Axios.js */
// Axios构造函数
function Axios(defaultConfig) {
  this.defaults = defaultConfig;
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  }
}

/* axios/lib/core/InterceptorManager.js */
// InterceptorManager构造函数
function InterceptorManager() {
  // 默认空数组
  this.handlers= [];
}

// InterceptorManager原型上定义use方法 (上述业务中的use方法,其实就是调用了该方法)
InterceptorManager.prototype.use = function(fulfilled, rejected) {
    // 数组中push一个包含成功回调、失败回调的对象
    this.handlers.push({
      fulfilled: fulfilled,
      rejected: rejected
    });
    
    // 返回数组长度 - 1
    return this.handlers.length - 1;
}

// InterceptorManager原型上定义eject方法
InterceptorManager.prototype.eject = function(id) {
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
}

// InterceptorManager原型上定义forEach方法
InterceptorManager.prototype.forEach = function(fn) {
  utils.forEach(this.handlers, function(h) {
    if (h !== null) {
      fn(h);
    }
  });  
}

service.interceptors.request.use 原来就是向handlers数组push了一个对象,可打印信息查看,代码如下:

console.log(service.interceptors.request.handlers);
// 结果如下
[
  {
    fulfilled: (config) => {...},
    rejedcted: (err) => {...}
  }
]

那么,在发送请求时,请求拦截器是如何运作的,代码如下:

/* axios/lib/core/Axios.js */
Axios.prototype.request = function(defaultConfigOrUrl, config) {
  ... ... ...

  var requestInterceptorChain = [];
  this.interceptors.request.forEach(function (interceptor) {
    // 将该实例的this.interceptors.request.handlers放入requestChain 
    requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  var promise;

  // dispatchRequest就是请求过程
  var chain = [dispatchRequest, undefined];
  Array.prototype.unshift.apply(chain, requestInterceptorChain);

  promise = Promise.resolve(config);
  while (chain.length) {
    // 链式调用,不断减少chain数组的长度,直至为空
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;

  ... ... ...   
}

 

这也便是说为什么axios是基于promise的,请求拦截器 --> 请求 --> 响应拦截器。

 

取消拦截器

取消拦截器功能,我觉得作用不大,代码如下:

var requestNumber = service.interceptors.request.use(fulfilled, rejected);

// 取消请求拦截器
service.interceptors.request.reject(requestNumber);

service.post({})

 

多个请求拦截器

主要讲多个请求拦截器的执行顺序,代码如下:

// 第一个请求拦截器
service.interceptors.request.use(fulfilled1, rejected1);

// 第二个请求拦截器
service.interceptors.request.use(fulfilled2, rejected2);

// 第三个请求拦截器
service.interceptors.request.use(fulfilled3, rejected3);

// 根据上述Axios.prototype.request方法,可以知道handlers数组:[fulfilled3, rejected3, fulfilled2, rejected2, fulfilled1, rejected1]

// 所以执行顺序:fulfilled3 --> fulfilled2 --> fulfilled1

 

posted @ 2022-05-11 17:16  小东博客之家  阅读(693)  评论(0编辑  收藏  举报