第 75 期 - Axios 源码剖析:理解其设计原理与核心特性
摘要
本文先对比 axios 的两种请求方式,然后通过构建简化版 axios 理解其核心原理,还解析了拦截器与动态请求方法的设计,展现 axios 的灵活性与高效性。
一、axios 的两种请求方式
axios 在日常开发中有两种常用的调用方式:基于配置的请求和链式简化请求。
- 基于配置的请求像详细点餐,例如
axios({ method: 'post', url: '/user/12345' });
,适合精确控制请求细节场景。 - 链式简化请求类似简单点餐,如
axios.post('/user/12345');
,简洁直观适合简单请求。这两种方式虽然常用,但我们需要深入 axios 源码才能理解它如何实现这两种不同风格。
二、Axios 的核心原理
(一)编写简单的 Axios 实现
- 首先创建构造函数
function Axios(config) { this.defaults = config; this.interceptors = { request: {}, response: {} };}
,这里定义了默认配置对象和拦截器对象。 - 接着给原型添加方法,如
Axios.prototype.request = function(config) { console.log('发送 Ajax 请求类型: ' + config.method);};
等,request
是通用请求函数,get
和post
是其快捷方式。
(二)Axios 的巧妙设计
- 为使
axios(config)
和axios.post()
正常工作,axios 返回既是函数又是对象的实例。简化实现如function createInstance(config) { const instance = Axios.prototype.request; instance.get = Axios.prototype.get; instance.post = Axios.prototype.post; return instance;}
。 - 真正的 axios 实现更复杂,核心逻辑在
function createInstance(config) { var context = new Axios(config); var instance = Axios.prototype.request.bind(context); Object.keys(Axios.prototype).forEach(key => { instance[key] = Axios.prototype[key].bind(context); }); Object.keys(context).forEach(key => { instance[key] = context[key]; }); return instance;}
,这种设计让实例化对象多功能,体现了源码设计的精妙。
三、拦截器与动态请求方法的设计解析
(一)请求和响应拦截器
- axios 的请求和响应拦截器允许在请求前或响应后执行自定义操作。
- 其通过队列设计模式实现,核心逻辑如
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);}); while (chain.length) { promise = promise.then(chain.shift(), chain.shift());}
。这种设计类似订单在流水线上的处理,增加了代码灵活性与可维护性。
(二)动态创建请求方法
- 除了常见的
get
和post
,axios 还有其他 HTTP 方法。手动为每种方法写函数定义很繁琐,axios 通过动态创建请求函数解决。 - 例如
['delete', 'get', 'head', 'options'].forEach(method => { Axios.prototype[method] = function(url, config) { return this.request(Object.assign(config || {}, { method: method, url: url })); };});
等代码,不同 HTTP 方法对应不同请求,运行时动态生成,使代码简洁且增强扩展性。
通过上述对 axios 的剖析,我们能更好地理解其设计原理,在实际项目中更熟练运用 axios 并为代码设计带来灵感。
扩展阅读
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有