Files
admin-vben5/packages/effects/request/src/request-client/request-client.ts

142 lines
3.8 KiB
TypeScript
Raw Normal View History

import type { AxiosInstance, AxiosResponse } from 'axios';
2024-06-02 20:50:51 +08:00
import type {
HttpResponse,
RequestClientConfig,
RequestClientOptions,
} from './types';
import { bindMethods, merge } from '@vben/utils';
2024-06-02 20:50:51 +08:00
import axios from 'axios';
import { FileDownloader } from './modules/downloader';
import { InterceptorManager } from './modules/interceptor';
import { FileUploader } from './modules/uploader';
class RequestClient {
public addRequestInterceptor: InterceptorManager['addRequestInterceptor'];
public addResponseInterceptor: InterceptorManager['addResponseInterceptor'];
2024-06-02 20:50:51 +08:00
public download: FileDownloader['download'];
// 是否正在刷新token
public isRefreshing = false;
// 刷新token队列
public refreshTokenQueue: ((token: string) => void)[] = [];
2024-06-02 20:50:51 +08:00
public upload: FileUploader['upload'];
private readonly instance: AxiosInstance;
2024-06-02 20:50:51 +08:00
/**
* Axios实例
2024-06-08 16:33:49 +08:00
* @param options - Axios请求配置
2024-06-02 20:50:51 +08:00
*/
constructor(options: RequestClientOptions = {}) {
// 合并默认配置和传入的配置
const defaultConfig: RequestClientOptions = {
2024-06-02 20:50:51 +08:00
headers: {
'Content-Type': 'application/json;charset=utf-8',
},
responseReturn: 'raw',
2024-06-02 20:50:51 +08:00
// 默认超时时间
timeout: 10_000,
};
const { ...axiosConfig } = options;
2024-06-02 20:50:51 +08:00
const requestConfig = merge(axiosConfig, defaultConfig);
this.instance = axios.create(requestConfig);
bindMethods(this);
2024-06-02 20:50:51 +08:00
// 实例化拦截器管理器
const interceptorManager = new InterceptorManager(this.instance);
this.addRequestInterceptor =
interceptorManager.addRequestInterceptor.bind(interceptorManager);
this.addResponseInterceptor =
interceptorManager.addResponseInterceptor.bind(interceptorManager);
// 添加基础的响应处理,根据设置决定返回响应的哪一部分
this.addResponseInterceptor<HttpResponse>({
fulfilled: (response) => {
const { config, data: responseData, status } = response;
if (config.responseReturn === 'raw') {
return response;
}
const { code, data } = responseData;
if (status >= 200 && status < 400 && code === 0) {
return config.responseReturn === 'body' ? responseData : data;
}
throw Object.assign({}, response, { response });
},
});
2024-06-02 20:50:51 +08:00
// 实例化文件上传器
const fileUploader = new FileUploader(this);
this.upload = fileUploader.upload.bind(fileUploader);
// 实例化文件下载器
const fileDownloader = new FileDownloader(this);
this.download = fileDownloader.download.bind(fileDownloader);
}
/**
* DELETE请求方法
*/
public delete<T = any>(
url: string,
config?: RequestClientConfig,
): Promise<T> {
2024-06-02 20:50:51 +08:00
return this.request<T>(url, { ...config, method: 'DELETE' });
}
/**
* GET请求方法
*/
public get<T = any>(url: string, config?: RequestClientConfig): Promise<T> {
2024-06-02 20:50:51 +08:00
return this.request<T>(url, { ...config, method: 'GET' });
}
/**
* POST请求方法
*/
public post<T = any>(
url: string,
data?: any,
config?: RequestClientConfig,
2024-06-02 20:50:51 +08:00
): Promise<T> {
return this.request<T>(url, { ...config, data, method: 'POST' });
}
/**
* PUT请求方法
*/
public put<T = any>(
url: string,
data?: any,
config?: RequestClientConfig,
2024-06-02 20:50:51 +08:00
): Promise<T> {
return this.request<T>(url, { ...config, data, method: 'PUT' });
}
/**
*
*/
public async request<T>(
url: string,
config: RequestClientConfig,
): Promise<T> {
2024-06-02 20:50:51 +08:00
try {
const response: AxiosResponse<T> = await this.instance({
url,
...config,
});
return response as T;
} catch (error: any) {
throw error.response ? error.response.data : error;
}
}
}
export { RequestClient };