接口请求封装
对于axios的接口请求基本已经是很成熟的方案了,接下来的代码是使用AbortController取消接口请求的一个简单案例供大家参考。
使用pinia来保存接口的唯一标识用以之后的取消功能
import { defineStore } from "pinia";
import { store } from "@/store";
interface RequestController {
key: string;
controller: AbortController;
}
const useCancelRequestsStore = defineStore("requests", {
state: () => ({
controllers: new Map<string, RequestController>()
}),
actions: {
/**
* 添加请求,并返回相应的 AbortSignal
*
* @param key 请求的唯一标识符
* @returns 如果请求已存在,则返回 undefined;否则返回相应的 AbortSignal
*/
addRequest(key: string): AbortSignal | undefined {
// 如果已经存在该key的请求,则输出警告信息
if (this.controllers.has(key)) {
console.warn(`Request with key ${key} already exists.`);
// 返回undefined,或者根据需求可以抛出异常
return undefined; // 或者可以抛出异常,取决于你的需求
}
// 创建一个新的AbortController实例
const controller = new AbortController();
// 将key和controller对象存入controllers集合中
this.controllers.set(key, { key, controller });
// 返回controller的signal对象
return controller.signal;
},
/**
* 删除已完成的请求,防止map中存在不需要取消的请求
*
* @param key 请求的key值
*/
delRequest(key: string) {
// 根据给定的 key 从 controllers 中删除对应的请求控制器
this.controllers.delete(key);
},
/**
* 取消请求
*
* @param key 请求的标识
*/
cancelRequest(key: string) {
// 获取指定 key 的请求控制器
const entry = this.controllers.get(key);
if (entry) {
try {
// 调用请求控制器的 abort 方法取消请求
entry.controller.abort();
// 输出成功取消请求的信息
console.log(`Request with key ${key} was successfully aborted.`);
// 从控制器集合中删除已取消的请求控制器
this.controllers.delete(key);
} catch (error) {
// 输出取消请求失败的信息及错误原因
console.error(`Failed to abort request with key ${key}:`, error);
}
} else {
// 输出没有找到对应 key 的请求信息
console.warn(`No request found with key ${key} to abort.`);
}
},
/**
* 取消所有请求
*
* 遍历所有的请求控制器,并逐个取消它们。
* 取消请求后,在控制台输出一条消息,指示已取消该请求。
* 如果取消请求时发生错误,则在控制台输出一条错误消息,指示已取消失败。
* 清除所有请求控制器,并在控制台输出一条消息,指示所有请求已取消。
*/
cancelAllRequests() {
// 遍历controllers数组
this.controllers.forEach((entry, key) => {
try {
// 调用每个entry的controller的abort方法取消请求
entry.controller.abort();
// 输出日志,表示已取消指定key的请求
console.log(
`Request with key ${key} was aborted as part of cancelAllRequests.`
);
} catch (error) {
// 如果取消请求时发生错误,输出错误日志
console.error(
`Failed to abort request with key ${key} during cancelAllRequests:`,
error
);
}
});
// 清空controllers数组
this.controllers.clear();
// 输出日志,表示所有请求已取消
console.log("All requests have been cancelled.");
}
}
});
export function useCancelRequestsHook() {
return useCancelRequestsStore(store);
}
在公共的request封装中引用store
/**
* 设置http请求拦截器
*
* @returns 无返回值
*/
private httpInterceptorsRequest(): void {
PureHttp.axiosInstance.interceptors.request.use(
async (config: PureHttpRequestConfig): Promise<any> => {
/**
* 添加取消请求功能
*/
if (!config.signal && config.requestId) {
// 支持用户通过业务侧使用,方便单独清除页面中的请求
const signal = useCancelRequestsHook().addRequest(config.requestId);
config.signal = signal;
}
// ... 省略
},
error => {
return Promise.reject(error);
}
);
}
/**
* 发起网络请求
*
* @param method 请求方法,例如:'get', 'post'
* @param url 请求地址
* @param param 请求参数
* @param axiosConfig 额外的Axios配置
* @returns 返回请求结果的Promise
*/
public request<T>(
method: RequestMethods,
url: string,
param?: AxiosRequestConfig,
axiosConfig?: PureHttpRequestConfig
): Promise<T> {
// 定义一个唯一Id用以释放store中存储的标识
const requestId = uuid(64);
const config = {
method,
url,
requestId,
...param,
...axiosConfig
} as PureHttpRequestConfig;
// 创建一个新的Promise对象,用于处理异步请求
// 单独处理自定义请求/响应回调
return new Promise((resolve, reject) => {
PureHttp.axiosInstance
.request(config)
// 请求成功时,将响应数据通过resolve返回
.then((response: undefined) => {
resolve(response);
})
// 请求失败时,将错误信息通过reject返回
.catch(error => {
reject(error);
})
// 请求完成后执行,无论成功或失败
.finally(() => {
/* 接口请求完毕,清除取消标识 */
useCancelRequestsHook().delRequest(config.requestId);
});
});
}
}