传送门:ios
Axios
类的构造函数:axios
// /lib/core/Axios.js function Axios(instanceConfig) { // 默认配置 this.defaults = instanceConfig; // 拦截器 this.interceptors = { // 请求拦截器 request: new InterceptorManager(), // 响应拦截器 response: new InterceptorManager() }; }
Axios.prototype.request
方法是Axios
类原型方法中的重中之重。segmentfault
Axios.prototype.request = function request(config) { // 用于API中的 axios(config) 或 axios(url[, config]) if (typeof config === 'string') { config = arguments[1] || {}; config.url = arguments[0]; } else { config = config || {}; } // 将传入的配置与默认配置合并 config = mergeConfig(this.defaults, config); // 设置请求方法 config.method = config.method ? config.method.toLowerCase() : 'get'; // 请求拦截 // 发送请求 // 响应拦截 }
在分析Axios.prototype.request
中拦截器与请求相关代码以前,要先分析拦截器的原理数组
// /lib/core/InterceptorManager.js function InterceptorManager() { this.handlers = []; } // 将一个拦截器添加到handlers数组 // 对应API中的 axios.interceptors.request.use 与 axios.interceptors.resopnse.use // 返回拦截器的ID InterceptorManager.prototype.use = function use(fulfilled, rejected) { this.handlers.push({ fulfilled: fulfilled, rejected: rejected }); return this.handlers.length - 1; }; // 移除指定ID的拦截器 InterceptorManager.prototype.eject = function eject(id) { if (this.handlers[id]) { this.handlers[id] = null; } }; // 遍历执行handlers数组中的拦截器,跳过被eject成null的项 InterceptorManager.prototype.forEach = function forEach(fn) { utils.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } }); }; module.exports = InterceptorManager;
Axios.prototype.request = function request(config) { /* 配置相关代码 */ // 请求链 chain // 首先加入发送请求的方法和 undefined var chain = [dispatchRequest, undefined]; var promise = Promise.resolve(config); // 从请求链的头部将请求拦截器依次加入 this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { chain.unshift(interceptor.fulfilled, interceptor.rejected); }); // 从请求链的尾部将相应拦截器依次加入 this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { chain.push(interceptor.fulfilled, interceptor.rejected); }); // 遍历请求链,造成 promise 链 while (chain.length) { promise = promise.then(chain.shift(), chain.shift()); } // 返回promise链 return promise; }
流程图以下:promise
这里尤为应注意到请求链中请求拦截器的顺序(handlers数组的倒序),在使用axios.interceptors.request.use
时,要留意这一点。函数
另外,Axios
类还有Axios.prototype.get
、Axios.prototype.post
、Axios.prototype.delete
等方法,实际上都是修改了Axios.prototype.request
参数config
中的method
属性。post
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { Axios.prototype[method] = function (url, config) { return this.request(utils.merge(config || {}, { method: method, url: url })); }; }); utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { Axios.prototype[method] = function (url, data, config) { return this.request(utils.merge(config || {}, { method: method, url: url, data: data })); }; });
分析完Axios
类,咱们再次回到入口文件:this
// /lib/axios.js function createInstance(defaultConfig) { // 建立一个Axios类的实例,获得一个上下文环境 // 包含defaults配置与拦截器(详见/lib/core/Axios.js) var context = new Axios(defaultConfig); // instance是一个函数(request请求方法) // this绑定到context上下文 var instance = bind(Axios.prototype.request, context); // 将Axios.prototype的各方法绑定到instance上 // 其中this做用域为context上下文 utils.extend(instance, Axios.prototype, context); // 将context中的属性(defaults与拦截器)绑定到instance实例中 utils.extend(instance, context); return instance; } var axios = createInstance(defaults); /* ... */ modules.exports = axios;
如今咱们就能够在Axios
类中找到,axios
中的defaults
、interceptors
属性,以及axios()
、axios.get()
、axios.post()
等请求方法的由来。url