在现代 Web 开发中,处理异步请求是一个常见的需求。特别是在处理长时间运行的请求或需要取消未完成的请求时,使用 AbortController
可以帮助我们更好地控制和管理这些请求。本文将介绍如何结合 Axios 和 AbortController
实现请求控制和取消功能。
什么是 AbortController?
AbortController
是一个用于控制和取消 Web 请求的接口。它允许你在需要时中止一个或多个请求。AbortController
和 AbortSignal
是 Fetch API 的一部分,主要用于取消正在进行的 fetch 请求,但也可以用于其他异步操作。
Axios 类型定义
在 TypeScript 中,使用 Axios 时,我们可以利用其提供的类型定义来进行类型检查和代码提示。以下是一些常用的 Axios 类型定义:
AxiosInstance
:表示 Axios 实例的类型。包含 Axios 实例上的所有方法和属性,如get
、post
、request
等。AxiosRequestConfig
:表示 Axios 请求配置的类型。包含请求的所有配置选项,如url
、method
、headers
、params
、data
等。AxiosResponse
:表示 Axios 响应的类型。包含响应的所有属性,如data
、status
、statusText
、headers
、config
等。CreateAxiosDefaults
:包含创建 Axios 实例时的所有默认配置选项。InternalAxiosRequestConfig
:表示 Axios 内部请求配置的类型。包含 Axios 内部使用的请求配置选项,通常不需要在外部代码中直接使用。
实现步骤
我们将通过以下步骤实现请求控制和取消功能:
- 创建一个
AbortController
实例,并将其与请求关联。 - 使用 Axios 请求拦截器将
AbortSignal
传递给请求。 - 使用 Axios 响应拦截器在请求完成后移除
AbortController
。 - 提供方法来取消特定请求或所有请求。
代码实现
1. 安装 Axios 和 TypeScript
首先,确保你已经安装了 Axios 和 TypeScript:
bash
npm install axios
npm install typescript
2. 创建 RequestController 类
typescript
import axios, {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
CreateAxiosDefaults,
InternalAxiosRequestConfig,
} from 'axios';
class RequestController {
private instance: AxiosInstance;
private abortControllerMap: Map<string, AbortController>;
constructor(config?: CreateAxiosDefaults) {
this.instance = axios.create(config);
this.abortControllerMap = new Map();
this.setupInterceptors();
}
private setupInterceptors() {
// 请求拦截器
this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
const controller = new AbortController();
config.signal = controller.signal; // 挂载控制器的发射器
const url = config.url || '';
this.abortControllerMap.set(url, controller); // 添加控制器进入 map
return config;
});
// 响应拦截器
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
const url = response.config.url || '';
this.abortControllerMap.delete(url); // 删除 map 里的本条数据
return response;
},
(error) => {
const url = error.config.url || '';
this.abortControllerMap.delete(url); // 删除 map 里的本条数据
return Promise.reject(error);
}
);
}
// 取消指定请求
public cancelRequest(url: string) {
const controller = this.abortControllerMap.get(url);
if (controller) {
controller.abort(); // 使用控制器终止请求
this.abortControllerMap.delete(url); // 删除 map 里的本条数据
}
}
// 取消所有请求
public cancelAllRequests() {
for (const [, controller] of this.abortControllerMap) {
controller.abort(); // 使用控制器终止请求
}
this.abortControllerMap.clear(); // 清空请求列表
}
// 发起请求
public request<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return this.instance.request(config);
}
}
export default new RequestController();
解释
-
导入部分:
typescriptimport axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig, } from 'axios';
- 导入 Axios 库和相关类型定义。
-
定义类和私有属性:
typescriptclass RequestController { private instance: AxiosInstance; private abortControllerMap: Map<string, AbortController>; constructor(config?: CreateAxiosDefaults) { this.instance = axios.create(config); this.abortControllerMap = new Map(); this.setupInterceptors(); } }
- 定义
RequestController
类。 - 使用
private
关键字定义私有属性instance
和abortControllerMap
。 instance
是一个 Axios 实例,用于发起 HTTP 请求。abortControllerMap
是一个Map
,用于存储每个请求的AbortController
。
- 定义
-
设置拦截器:
typescriptprivate setupInterceptors() { // 请求拦截器 this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => { const controller = new AbortController(); config.signal = controller.signal; // 挂载控制器的发射器 const url = config.url || ''; this.abortControllerMap.set(url, controller); // 添加控制器进入 map return config; }); // 响应拦截器 this.instance.interceptors.response.use( (response: AxiosResponse) => { const url = response.config.url || ''; this.abortControllerMap.delete(url); // 删除 map 里的本条数据 return response; }, (error) => { const url = error.config.url || ''; this.abortControllerMap.delete(url); // 删除 map 里的本条数据 return Promise.reject(error); } ); }
- 在请求拦截器中,创建一个
AbortController
实例,并将其signal
传递给请求配置。 - 在响应拦截器中,请求完成后移除
AbortController
。
- 在请求拦截器中,创建一个
-
取消指定请求:
typescriptpublic cancelRequest(url: string) { const controller = this.abortControllerMap.get(url); if (controller) { controller.abort(); // 使用控制器终止请求 this.abortControllerMap.delete(url); // 删除 map 里的本条数据 } }
- 提供
cancelRequest
方法,用于取消特定请求。
- 提供
-
取消所有请求:
typescriptpublic cancelAllRequests() { for (const [, controller] of this.abortControllerMap) { controller.abort(); // 使用控制器终止请求 } this.abortControllerMap.clear(); // 清空请求列表 }
- 提供
cancelAllRequests
方法,用于取消所有请求。
- 提供
-
发起请求:
typescriptpublic request<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> { return this.instance.request(config); }
- 提供
request
方法,用于发起 HTTP 请求。
- 提供
使用示例
下面是一个使用 RequestController
类的示例,展示了如何发起请求和取消请求。
typescript
import RequestController from './RequestController';
// 发起请求
RequestController.request({
url: 'https://jsonplaceholder.typicode.com/posts',
method: 'GET',
})
.then((response) => {
console.log('Response:', response.data);
})
.catch((error) => {
if (error.name === 'AbortError') {
console.log('Request aborted');
} else {
console.error('Request error:', error);
}
});
// 取消特定请求
RequestController.cancelRequest('https://jsonplaceholder.typicode.com/posts');
// 取消所有请求
RequestController.cancelAllRequests();
总结
通过结合 Axios 和 AbortController
,我们可以实现对请求的精细控制和管理。本文介绍了如何在 TypeScript 中使用 private
关键字定义一个私有的 Axios 实例属性,并结合 AbortController
实现请求控制和取消功能。希望这篇文章对你有所帮助,让你在处理异步请求时更加得心应手。
如果你有任何问题或建议,欢迎在评论区留言讨论。谢谢阅读!