axios源码分析--拦截器

axios支持拦截请求和响应ios

使用方法

//设置请求拦截器
const myInterceptor = axios.interceptors.request.use((config)=>{
    return config;
}, (error) => {
    return Promise.reject(error);
});
//取消请求拦截器
axios.interceptors.request.eject(myInterceptor);
   
axios('https://api.github.com/users/mzabriskie').then(function (res) {
    //todo
}).catch(function(){
    //todo
})
复制代码

response的使用和request是同样的。git

有一点须要注意是拦截器的执行顺序,request 拦截器先加入的后执行,response 拦截器则是先加入的先执行。github

源码分析

axios的基本调用流程,参照文章传送门。axios(url).then().catch(),实际上是调用Axios.prototype.request方法axios

在文件axios/lib/core/Axios.jsapi

function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(), //请求拦截器
    response: new InterceptorManager() //响应拦截器
  };
}

Axios.prototype.request = function request(config) {
  //...
  //设置config
    
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  //将添加的请求拦截器加到chain中
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  //将添加的响应拦截器加到chain中
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};
复制代码

咱们来看看new InterceptorManager()定义了怎样的对象,进入到axios/lib/core/InterceptorManager.js文件promise

function InterceptorManager() {
  this.handlers = [];
}
//添加拦截器,返回下标做为ID
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected
  });
  return this.handlers.length - 1; //返回下标做为ID
};
//根据下标ID,进行移除拦截器
InterceptorManager.prototype.eject = function eject(id) {
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
};
//遍历全部添加的拦截器
InterceptorManager.prototype.forEach = function forEach(fn) {
  utils.forEach(this.handlers, function forEachHandler(h) {
    if (h !== null) {
      fn(h);
    }
  });
};
复制代码

拦截器管理模块InterceptorManager,创建了一个handlers队列来管理添加的拦截器。bash

在Axios.prototype.request方法中,使用chain.unshift将this.interceptors.request添加到chain中,因此request 拦截器先加入的后执行。可是,使用chain.push将this.interceptors.response,因此response 拦截器先加入的先执行。源码分析

最终Axios.prototype.request方法返回的promise等价于下面代码,post

Promise.resolve(config)
.then(interceptors.request, interceptors.request)
...//多个请求拦截器
.then(dispatchRequest, undefined)
...//多个响应拦截器
.then(interceptors.response, interceptors.response)
复制代码

参考连接

axios执行原理了解一下!ui

axios源码分析——拦截器

相关文章
相关标签/搜索