ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

axios源码解析 - 请求拦截器

2022-05-11 15:02:34  阅读:220  来源: 互联网

标签:... axios service interceptors request 拦截器 InterceptorManager 源码


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/core/Axios.js */
// Axios构造函数
function Axios(defaultConfig) {
  this.defaults = defaultConfig;
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  }
}

/* axios/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.prototype.request = function(defaultConfigOrUrl, config) {
  ... ... ...

  var requestInterceptorChain = [];
  this.interceptors.request.forEach(function (interceptor) {
    // 将该实例的this.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

 

标签:...,axios,service,interceptors,request,拦截器,InterceptorManager,源码
来源: https://www.cnblogs.com/wuzhendong/p/16257163.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有