入行4年时间,惭愧的很,第一次看axios源码。不看不知道,一看吓一跳。不理解并且不懂大佬们的这些个想法怎么蹦跶出来的,绝了。有空可以看看axios源码
很好奇的,也是第一个惊讶的就是拦截器。
添加拦截器
class InterceptorManager{
constructor() {
// 初始化数组
this.handlers = [];
}
// use函数就是平常咱们使用的
// interceptors.request.use(func1,func2)
// interceptors.response.use(func1,func2)
use(fulfilled, rejected, options){
this.handlers.push({
// 传进来的第一个参数 key:fulfilled value:传的第一个函数
fulfilled,
// 传进来的第二个参数 key:rejected value:传的第二个函数
rejected,
synchronous: options ? options.synchronous : false,
runWhen: options ? options.runWhen : null
});
}
}
使用拦截器
class Axios{
// 构造函数吧
constructor(instanceConfig) {
this.defaults = instanceConfig;
// 拦截器
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
request(configOrUrl, config){
// ....省略逻辑
// 定义请求拦截器数组
const requestInterceptorChain = [];
// 数组循环
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
// 将拦截器中的fulfilled、rejected添加到requestInterceptorChain的 开头 unshift呀
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 定义响应的拦截器数组
const responseInterceptorChain = [];
// 数组循环
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
// 将拦截器中的fulfilled、rejected添加到responseInterceptorChain的 末尾 push呀
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
// 核心链路
// dispatchRequest 适配器来了 第二个惊讶的地方
const chain = [dispatchRequest.bind(this), undefined];
// 将请求拦截器数组添加到chain的 开头
chain.unshift.apply(chain, requestInterceptorChain);
// 将响应拦截器数组添加到chain的 尾部
chain.push.apply(chain, responseInterceptorChain);
// chain数组长度
len = chain.length;
// 构造一个promise对象
promise = Promise.resolve(config);
while (i < len) {
// promise成功 执行第一个chain[i++]函数
// 繁殖 执行第二个
promise = promise.then(chain[i++], chain[i++]);
}
return promise;
// ... 其他业务逻辑
}
}
不管用get方式还是post方式、put等请求方式请求数据也好 都会执行上述request方法 接下来就是业务逻辑处理以及拦截器的调用等。dispatchRequest.bind(this) 返回一个函数,放到then方法的第一个参数上
适配器
export default function dispatchRequest(config) {
// ... 其他业务逻辑
// 获取自己传入的适配器或者是默认的适配器
// 默认两种 一种http(nodejs) 一个xhr(浏览器)
const adapter = adapters.getAdapter(config.adapter || defaults.adapter);
// 由于adapter是一个promise对象 顾可以用then方法处理成功/失败回调
return adapter(config).then(function onAdapterResolution(response) {
throwIfCancellationRequested(config);
// 响应数据转换
response.data = transformData.call(
config,
config.transformResponse,
response
);
response.headers = AxiosHeaders.from(response.headers);
return response;
}, function onAdapterRejection(reason) {
if (!isCancel(reason)) {
throwIfCancellationRequested(config);
// 响应数据转换
if (reason && reason.response) {
reason.response.data = transformData.call(
config,
config.transformResponse,
reason.response
);
reason.response.headers = AxiosHeaders.from(reason.response.headers);
}
}
return Promise.reject(reason);
});
}
主要看是咱们传入的适配器还是使用axios自带的默认适配器,反正我是一直用的默认适配器,返回了一个Promise对象。默认的适配器有两种,adapter: ['xhr', 'http']
http适配器
// 判断是否是nodejs环境
const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process';
export default isHttpAdapterSupported && function httpAdapter(config) {
// 返回一个promise对象
return new Promise((resolve, reject) => {
// 业务逻辑处理...
})
}
xhr适配器
// 判断是否是浏览器环境
const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';
export default isXHRAdapterSupported && function (config) {
// 返回一个promise对象
return new Promise((resolve, reject) => {
// 业务逻辑处理...
})
}