现在来看axios的核心,构造函数Axios,它本身就是一个构造函数,然后在其原型prototype上绑定了一些方法,拦截器就在this.interceptors上.
拦截器为何可以拦截?因为在发送请求之前,config会先传给request拦截器,处理之后传给dispatchRequest(也就是发送请求的方法),然后返回的结果传给response拦截器,response做出操作后再将结果返回
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(), // InterceptorManager也是一个构造函数
response: new InterceptorManager()
};
}
原型prototype添加了request方法(用来发送请求),getUri方法(用来建立请求的路径),还有就是一些方法的别名,比如axios.get()这种写法,就是在prototype上添加了get方法,所以实例上可以访问的到
源码分析如下
'use strict';
var utils = require('./../utils');
var buildURL = require('../helpers/buildURL');
var InterceptorManager = require('./InterceptorManager');
var dispatchRequest = require('./dispatchRequest');
var mergeConfig = require('./mergeConfig');
/**
* 构造函数Axios
*
* @param {Object} instanceConfig 默认配置
*/
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(), // InterceptorManager也是一个构造函数
response: new InterceptorManager()
};
}
/**
* 分发一个请求
*
* @param {Object} config 请求的配置 (跟默认配置合并)
*/
Axios.prototype.request = function request(config) { // config就是axios({})中的{}
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof config === 'string') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
config = mergeConfig(this.defaults, config);
// Set config.method
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = 'get';
}
// filter out skipped interceptors 过滤拦截器
var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
// forEach方法在InterceptorManager文件中, 其本质还是utils文件中的forEach方法, 参考axios源码(三)
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
// interceptor就是this.handler的每个元素, 参见InterceptorManager文件
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(function pushResponseInterceptors(interceptor) {
// 跟上面一样
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
var promise;
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;
}
var newConfig = config;
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break;
}
}
try {
promise = dispatchRequest(newConfig);
} catch (error) {
return Promise.reject(error);
}
while (responseInterceptorChain.length) {
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
}
return promise;
};
Axios.prototype.getUri = function getUri(config) {
config = mergeConfig(this.defaults, config);
return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, '');
};
// Provide aliases for supported request methods 给请求的方法提供一个别名
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: (config || {}).data
}));
};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: data
}));
};
});
module.exports = Axios;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。