js
class Axios {
constructor(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
request(configOrUrl, config) {
if (typeof configOrUrl === 'string') {
config = config || {};
config.url = configOrUrl;
} else {
config = configOrUrl || {};
}
config = mergeConfig(this.defaults, config);
const {transitional, paramsSerializer, headers} = config;
if (transitional !== undefined) {
validator.assertOptions(transitional, {
silentJSONParsing: validators.transitional(validators.boolean),
forcedJSONParsing: validators.transitional(validators.boolean),
clarifyTimeoutError: validators.transitional(validators.boolean)
}, false);
}
// 更高版本的 axios 将针对config.params 的 paramsSerializer 视作对象,支持 encode 和 serialize 方法
if (paramsSerializer !== undefined) {
validator.assertOptions(paramsSerializer, {
encode: validators.function,
serialize: validators.function
}, true);
}
config.method = (config.method || this.defaults.method || 'get').toLowerCase();
let contextHeaders;
contextHeaders = headers && utils.merge(
headers.common,
headers[config.method]
);
contextHeaders && utils.forEach(
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
(method) => {
delete headers[method];
}
);
config.headers = AxiosHeaders.concat(contextHeaders, headers);
// 请求拦截器从数组头部推入
const requestInterceptorChain = [];
let synchronousRequestInterceptors = true;
// 注意:这里拦截器的遍历使用的是其原型上的forEach方法(会过滤null项)
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return;
}
// 所有请求拦截器的synchronous都设置为true时,才会触发同步执行机制
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 响应拦截器 从数组尾部推入
const responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
let promise;
let i = 0;
let len;
// 请求拦截器 异步的场景,全部按照promise链执行
if (!synchronousRequestInterceptors) {
// 此处只是bind绑定dispatchRequest的this指向,dispatchRequest并没有执行
const chain = [dispatchRequest.bind(this), undefined];
chain.unshift.apply(chain, requestInterceptorChain);
chain.push.apply(chain, responseInterceptorChain);
/*
执行到这里,整个chain的形式是这样的:
[requestResolve, requestReject, ..., dispatchResolve, dispatchReject, responseResolve, responseReject, ...]
*/
len = chain.length;
promise = Promise.resolve(config);
while (i < len) {
promise = promise.then(chain[i++], chain[i++]);
}
return promise;
}
// 请求拦截器 同步
len = requestInterceptorChain.length;
let newConfig = config;
i = 0;
while (i < len) {
const onFulfilled = requestInterceptorChain[i++];
const onRejected = requestInterceptorChain[i++];
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected.call(this, error);
break;
}
}
// dispatchRequest和响应拦截器 依旧是promise.then微任务
try {
// 此处利用call执行dispatchRequest,返回的是promise
promise = dispatchRequest.call(this, newConfig);
} catch (error) {
return Promise.reject(error);
}
i = 0;
len = responseInterceptorChain.length;
while (i < len) {
promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);
}
return promise;
}
}
Axios class
中的核心在于 request
方法。
在 request
方法中,主要涉及到了三方面:
- 请求拦截器
interceptor-request
- 分发请求
dispatchRequest
- 响应拦截器
interceptor-response
请求拦截器和响应拦截器的构造函数都是 InterceptorManager
。
因此需要接着了解下 InterceptorManager
和 dispatchRequest
这俩方面的实现原理。
TIP
额外说明一下 synchronous
配置项对于请求拦截器的影响:
假设有:
interceptor-request
transform-request
transform-response
interceptor-response
main thread
那么对于 synchronous
为 false
,此时会按照 promise
链的顺序来执行,又因为都是 then
微任务,所以执行顺序是 1、2、3、4、5
。
如果声明 synchronous
为 true
,请求拦截器会以同步的方式进行。此时 1、2
不会被推到 promise
链中,但 3、4
实际上是 promise
链中,此时执行顺序为 1、2、5、3、4
。