实现拦截器1
拦截器的作用就是拦截请求或响应。我们在请求发出去前进行拦截,就可以对请求进行统一的处理,比如往请求头添加字段等;我们也可在响应返回之前对后端数据进行统一的处理。 我们可以通过以下方式来添加一个拦截器
// 添加请求拦截器
axios.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
axios.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response;
},
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);
根据以上代码,我们可以知道axios是通过 axios.interceptors
来添加拦截器,因此我们在 Axios
类中实现拦截器的功能,首先我们在Axios
构造函数中通 new InterceptorManager()
分别实例化请求和响应的拦截管理对象,该管理对象的作用是负责添加、删除、处理拦截器。
/**
* axios实例构造函数
*
* @param {Object} instanceConfig 实例配置对象
*/
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager(),
};
}
上面例子中添加的请求拦截器和响应拦截器会在 request
请求中被使用。request函数通过 this.interceptors.request.forEach
把添加的请求拦截器依次插入到 chain
数组的 dispatchRequest
方法前面,这样子就可以在请求发出去前先进行处理,同理通过 this.interceptors.response.forEach
把添加的响应拦截器依次插入到 chain
数组的 dispatchRequest
方法后面,就可在响应返回前进行拦截处理。
Axios.prototype.request = function request(config) {
// 以上部分代码请参考前面的章节或最后一章提供的参考资料
var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);
// 把请求拦截器添加到requestInterceptorChain数组中
var requestInterceptorChain = [];
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 把响应拦截器添加到responseInterceptorChain数组中
var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
// 把请求拦截处理函数添加到chain数组前面去,在dispatchRequest请求发出前进行拦截处理
Array.prototype.unshift.apply(chain, requestInterceptorChain);
// 把响应拦截处理函数添加到chain数组前面去,在响应返回前进行拦截处理
chain = chain.concat(responseInterceptorChain);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
// 添加拦截器后相当于 Promise.resolve(config)
// .then(reqFulfilled, reqRejected) // 请求拦截处理函数
// .then(dispatchRequest, undefined)
// .then(resFulfilled, resRejected) // 响应拦截处理函数
return promise;
};
接下来,我们在 core
文件夹下创建 InterceptorManager.js
文件,在文件里我们实现 InterceptorManager
拦截管理类。该类提供三个方法,其中 use
方法就是用来添加拦截器,并返回一个 id,该 id 可用于删除当前拦截器。第二个方法是 eject
方法,该方法传入 use
方法返回的 id 就可以删除对应的拦截器。第三个方法是 forEach
,该方法传入一个回调函数,在该函数中依次处理拦截器
"use strict";
var utils = require("../utils");
function InterceptorManager() {
this.handlers = [];
}
/**
* 添加新的拦截器到栈
*
* 这两个参数最终会被promise.then使用, promise.then(fulfilled, rejected)
*
* @param {Function} fulfilled promise.then的处理函数, 即上面例子中请求发送前的处理函数
* @param {Function} rejected promise.reject的处理函数, 即上面例子中请求失败的处理函数
*
* @return {Number} 被用来移除拦截器的id
*/
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected,
});
return this.handlers.length - 1;
};
/**
* 从栈中移除一个拦截器
*
* @param {Number} id The ID that was returned by `use`
*/
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
};
/**
* 迭代所有被注册的拦截器
*
* 该方法可以忽略值为null的拦截器
*
* @param {Function} fn 处理拦截器对象的函数
*/
InterceptorManager.prototype.forEach = function forEach(fn) {
// 迭代处理所有的拦截器
utils.forEach(this.handlers, function forEachHandler(h) {
if (h !== null) {
// fn函数为unshiftRequestInterceptors、pushResponseInterceptors函数,参数为interceptor拦截器对象
// h参数为handlers中保存的interceptor拦截器对象,包含fulfilled, rejected两个拦截处理方法
fn(h);
}
});
};
module.exports = InterceptorManager;