axios中拦截器分为请求拦截器和相应拦截器,请求拦截器用于在request之前的预处理,比如带上token,相应拦截器可以对response做统一处理。
初始化
首先看一下Interceptor的初始化过程, 在axios实例上由变量interceptors统一保管拦截器,拦截器内部就是一个普通array。
//Axios.js
function Axios(instanceConfig) {
this.defaults = instanceConfig;
//拦截器
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
//InterceptorManager.js
function InterceptorManager() {
this.handlers = [];
}
添加拦截器
在axios中使用use函数添加Interceptor,下面看一下use函数的code
//InterceptorManager.js
InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected,
//默认情况下拦截是异步的
synchronous: options ? options.synchronous : false,
runWhen: options ? options.runWhen : null
});
return this.handlers.length - 1;
};
use方法调用时将一个对象添加到handlers中,fulfilled是请求/相应成功时调用的函数,rejected就是失败回调。
synchronous代表该拦截器是同步还是异步调用,默认情况下拦截器都是异步的,且只有所有拦截器都是同步的才会进入同步调用。
拦截器的执行过程
拦截器会在request(axios的核心请求函数)请求时执行。
//Axios.js/request
var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return;
}
//只要有一个拦截器是异步的,那么所有拦截器都异步调用
//如果所有拦截器都是同步的才进行同步调用
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
var responseInterceptorChain = [];
this.interceptors.response.forEach(functionpushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled,interceptor.rejected);
});
首先取出handlers中的拦截器,然后放入array中用于后续执行。
下面是拦截器异步执行的过程,这里使用unshift和concat将请求拦截器,request,响应拦截器拼接,按照顺序依次执行就可以实现先执行requestInterceptor,然后调用request,最后执行responseInterceptor。
然后先生成一个fulfilled状态的promise用于支持链式调用,通过while将promise.then连接在一起就实现了interceptor的异步链式调用。
if (!synchronousRequestInterceptors) {
//拼接拦截器数组
var chain = [dispatchRequest, undefined];
Array.prototype.unshift.apply(chain, requestInterceptorChain);
chain = chain.concat(responseInterceptorChain);
promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
下面再看一下拦截器的同步执行过程,相对于异步简单很多, 直接遍历执行就可以了。
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break;
}
}
summary
总结一下拦截器的执行过程