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源碼分析——攔截器

相關文章
相關標籤/搜索