为什么要封装
axios 本身已经很好用了,看似多次一举的封装则是为了让 axios 与项目解耦。
比如想要将网络请求换成 fetch,那么只需按之前暴露的 api 重新封装一下 fetch 即可,并不需要改动项目代码。
目标
- 统一请求API
- 使用接口数据时能有代码提示
文件结构
│ index.ts # 实例化封装类实例
│
├─http
│ request.ts # 封装axios
│
└─modules
login.ts # 业务模块
upload.ts
封装通用请求方法
先封装一个通用的方法 request,然后在此基础上封装出 http 方法:
class HttpRequest {
private readonly instance: AxiosInstance;
constructor(config: AxiosRequestConfig) {
this.instance = axios.create(config);
}
request<TReqBodyData, TResData, TResStructure = ResStructure<TResData>>(
config: AxiosRequestConfig<TReqBodyData>
): Promise<TResStructure> {
return new Promise<TResStructure>((resolve, reject) => {
this.instance
.request<any, AxiosResponse<TResStructure>>(config)
.then(res => {
// 返回接口数据
resolve(res?.data);
})
.catch(err => reject(err));
});
}
}
获得类型提示
我希望在使用请求方法时,可以得到后端接口请求参数的提示,并且希望在使用响应结果时,也能得到类型提示。
因此设计了三个泛型:
- TReqBodyData:请求体类型
- TResStructure:接口响应结构类型
- TResData:接口响应 data 字段数据类型
并提供了一个默认的响应结构。使用时可以根据需要改成项目中通用的接口规则。当然在具体方法上也支持自定义响应接口结构,以适应一些不符合通用接口规则的接口。
/** 默认接口返回结构 */
export interface ResStructure<TResData = any> {
code: number;
data: TResData;
msg?: string;
}
http 方法
由 request 方法封装出 http 方法同名的 api。
get<TReqBodyData, TResData, TResStructure = ResStructure<TResData>>(
config?: AxiosRequestConfig<TReqBodyData>
): Promise<TResStructure> {
return this.request({
...config, method: "GET" });
}
post<TReqBodyData, TResData, TResStructure = ResStructure<TResData>>(
config: AxiosRequestConfig<TReqBodyData>
): Promise<TResStructure> {
return this.request({
...config, method: "POST" });
}
...
文件上传
文件上传一般使用 formdata,我们也可以简易封装一下。
uploadFile 方法接收 4 个参数:
- axios config 对象
- 表单内容
- 文件对象
- 文件对象的表单字段名
- hash
- 文件名
- 更多的表单数据(可通过泛型
TOtherFormData
指定类型)
- 上传进度回调
- 取消上传的
signal
export interface UploadFileParams<TOtherFormData = Record<string, any>> {
file: File | Blob; // 文件对象
fileHash?: string; // hash
filename?: string; // 文件名
filed?: string; // formdata 中文件对象的字段
formData?: TOtherFormData; // 文件其他的参数(对象 key-value 将作为表单数据)
}
/**
* 文件上传
* @param {AxiosRequestConfig} config axios 请求配置对象
* @param {UploadFileParams} params 待上传文件及其一些参数
* @param {(event: AxiosProgressEvent) => void} uploadProgress 上传进度的回调函数
* @param {AbortSignal}cancelSignal 取消axios请求的 signal
* @returns
*/
uploadFile<TOtherFormData>(
config