Axios源码笔记 | 深度剖析 Cancel 取消请求体系,从源码到设计思路
一、引言
在前端开发的日常工作中,HTTP 请求是与后端进行数据交互的重要手段。然而,在一些复杂的业务场景下,比如用户频繁操作页面,可能会触发多个不必要的请求;或者在页面跳转时,之前发起的请求如果还未完成,就需要及时取消,以避免资源浪费和不必要的错误。Axios 作为一款广泛使用的 HTTP 客户端库,提供了强大的请求取消功能,这一功能主要集中在 axios-1.x/lib/cancel
目录下。
接下来,我们将深入剖析该目录下的 CanceledError.js
、CancelToken.js
和 isCancel.js
这三个文件,揭开 Axios 取消请求体系的神秘面纱。
二、CanceledError.js
源码解析
2.1 核心代码
'use strict';
var utils = require('../utils');
function CanceledError(message, config, request) {
Error.call(this);
this.message = message;
this.name = 'CanceledError';
this.config = config;
this.request = request;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CanceledError);
}
}
// 继承 Error 类
utils.inherits(CanceledError, Error);
module.exports = CanceledError;
这段代码定义了一个 CanceledError
类,用于表示请求被取消时抛出的错误。在构造函数中,首先调用 Error.call(this)
来继承 Error
类的基本属性,然后设置了自定义的属性 message
、name
、config
和 request
,分别用于存储错误信息、错误名称、请求配置和请求对象。Error.captureStackTrace
方法用于捕获错误堆栈信息,方便调试。最后,通过 utils.inherits
方法让 CanceledError
类正式继承 Error
类。
2.2 设计思路
在请求取消的场景下,需要有一个特定的错误类型来标识这种情况,以便开发者在代码中进行针对性的错误处理。通过创建 CanceledError
类,将请求取消相关的错误信息进行统一封装,并且保留了原始的请求配置和请求对象,有助于开发者更好地定位和解决问题。
2.3 重点逻辑
- 错误继承:通过
utils.inherits
方法实现CanceledError
类对Error
类的继承,确保它是一个标准的错误对象,能够被try...catch
语句捕获。 - 堆栈信息捕获:使用
Error.captureStackTrace
方法捕获错误堆栈信息,方便开发者在调试时快速定位问题。
三、CancelToken.js
源码解析
3.1 核心代码
'use strict';
var Cancel = require('./Cancel');
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// 已经取消,忽略
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if (this.reason) {
throw this.reason;
}
};
module.exports = CancelToken;
CancelToken
类是 Axios 取消请求体系的核心。构造函数接收一个 executor
函数作为参数,该函数会接收一个 cancel
函数。在构造函数内部,创建了一个 Promise
对象,当调用 cancel
函数时,会将 Promise
的状态置为 resolved
,并传递取消原因。CancelToken.source
是一个静态方法,用于便捷地创建 CancelToken
实例和对应的 cancel
函数。throwIfRequested
方法用于检查请求是否已经被取消,如果是则抛出取消原因。
3.2 设计思路
CancelToken
的设计目的是提供一种机制,让开发者可以在请求发送前或发送过程中取消请求。通过 Promise
来管理取消状态,使得取消操作可以与请求的生命周期进行交互。source
静态方法简化了 CancelToken
实例和 cancel
函数的创建过程,提高了开发效率。
3.3 重点逻辑
Promise
管理:利用Promise
来跟踪取消状态,当调用cancel
函数时,将Promise
状态置为resolved
,通知请求取消。source
方法:提供一种简洁的方式创建CancelToken
实例和对应的cancel
函数,方便开发者使用。throwIfRequested
方法:在请求发送前或处理响应时检查请求是否已被取消,避免无效的请求处理。
四、isCancel.js
源码解析
4.1 核心代码
'use strict';
export default function isCancel(value) {
return !!(value && value.__CANCEL__);
}
这段代码定义了一个名为 isCancel
的函数,用于判断一个值是否是由 Cancel
类创建的取消对象。通过双重取反操作,将结果转换为布尔值返回。
4.2 设计思路
在处理请求取消的错误时,开发者可能需要判断错误是否是由于请求取消引起的。isCancel
函数提供了一种简单而高效的方式来进行判断,提高了代码的健壮性和可维护性。
4.3 重点逻辑
- 属性检查:通过检查传入值是否存在且包含
__CANCEL__
属性来判断是否为取消对象。 - 布尔值转换:使用双重取反操作将结果转换为布尔值,确保返回值的类型一致。
五、结语
本文深入剖析了 Axios 1.x 版本中 axios-1.x/lib/cancel
目录下的三个核心文件。CanceledError.js
定义了请求取消时抛出的错误类型,为错误处理提供了统一的标准;CancelToken.js
作为取消请求体系的核心,通过 Promise
管理取消状态,提供了灵活的取消请求机制;isCancel.js
则提供了一个简单的工具函数,用于判断错误是否由请求取消引起。
通过阅读源码,我们不仅了解了 Axios 取消请求体系的实现原理,还学习到了一些优秀的编程思想和设计模式。例如,使用继承来扩展错误类型,利用 Promise
管理异步操作的状态,以及封装工具函数提高代码的复用性。这些知识可以帮助我们在实际开发中更好地处理请求取消的场景,优化用户体验。
- 点赞
- 收藏
- 关注作者
评论(0)