实现拦截器2
InterceptorManager
类的 use
方法,还接收一个options参数,该参数是一个对象类型,包含两个字段:一个是synchronous
属性,值是布尔类型;一个是runWhen
属性,值是函数类型。
runWhen函数的作用非常简单,就是接收一个合并后的配置对象(config),用户可以在这个函数里面自行决定当前的拦截器是否生效,返回false表示不生效,否则生效。
synchronous属性,用来决定rejected处理函数是同步生效,还是异步生效,默认是异步生效。这么说可能有点难以理解,我画了个图帮助大家理解。
我们假设通过多次调用axios.interceptors.request.use函数,添加了多个interceptor对象。那么synchronous=false,决定了rejected处理函数将会异步处理前一个interceptor拦截器里的fulfilled函数抛出的异常。synchronous=true, 决定了rejected处理函数将会同步处理同一个interceptor拦截器里的fulfilled函数抛出的异常。
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;
};
Axios.prototype.request = function request(config) {
// ...
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = "get";
}
// 把请求拦截器添加到requestInterceptorChain数组中
var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
// runWhen函数决定当前interceptor是否被应用
if (
typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false
) {
return;
}
// 用来决定rejected处理函数是同步生效,还是异步生效
synchronousRequestInterceptors = synchronousRequestInterceptors
&& interceptor.synchronous;
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 把响应拦截器添加到responseInterceptorChain数组中
var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
var promise;
// rejected异步生效
if (!synchronousRequestInterceptors) {
var chain = [dispatchRequest, undefined];
// 把请求拦截处理函数添加到chain数组前面去,在dispatchRequest请求发出前进行拦截处理
Array.prototype.unshift.apply(chain, requestInterceptorChain);
// 把响应拦截处理函数添加到chain数组前面去,在响应返回前进行拦截处理
chain = chain.concat(responseInterceptorChain);
promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
// rejected同步生效
var newConfig = config;
// 先执行请求拦截器
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break;
}
}
// 开始发出http请求
try {
promise = dispatchRequest(newConfig);
} catch (error) {
return Promise.reject(error);
}
// 执行响应拦截器
while (responseInterceptorChain.length) {
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
}
return promise;
};