refactor: 将请求封装重构为函数模式

This commit is contained in:
yangsy
2026-01-05 11:30:20 +08:00
parent fd70f63fc9
commit 263dd5edfc
4 changed files with 52 additions and 55 deletions

View File

@@ -1,8 +1,8 @@
import { useUserStore } from '@/stores'; import { useUserStore } from '@/stores';
import { getAppEnvConfig, RequestClient } from '@/utils'; import { createHttpClient, getAppEnvConfig } from '@/utils';
import type { AxiosError } from 'axios'; import type { AxiosError } from 'axios';
export const ndmClient = new RequestClient({ export const ndmClient = createHttpClient({
requestInterceptor: async (config) => { requestInterceptor: async (config) => {
const userStore = useUserStore(); const userStore = useUserStore();
const { lampAuthorization, lampClientId, lampClientSecret } = getAppEnvConfig(); const { lampAuthorization, lampClientId, lampClientSecret } = getAppEnvConfig();
@@ -25,7 +25,7 @@ export const ndmClient = new RequestClient({
const userStore = useUserStore(); const userStore = useUserStore();
await userStore.lampLogin(stationCode); await userStore.lampLogin(stationCode);
error.config.headers.token = userStore.lampLoginResultRecord?.[stationCode]?.token ?? ''; error.config.headers.token = userStore.lampLoginResultRecord?.[stationCode]?.token ?? '';
return ndmClient.requestInstance(error.config); return ndmClient.clientInstance(error.config);
} }
return Promise.reject(error); return Promise.reject(error);
}, },

View File

@@ -1,9 +1,9 @@
import router from '@/router'; import router from '@/router';
import { useUserStore } from '@/stores'; import { useUserStore } from '@/stores';
import { getAppEnvConfig, RequestClient } from '@/utils'; import { createHttpClient, getAppEnvConfig } from '@/utils';
import type { AxiosError } from 'axios'; import type { AxiosError } from 'axios';
export const userClient = new RequestClient({ export const userClient = createHttpClient({
requestInterceptor: (config) => { requestInterceptor: (config) => {
const userStore = useUserStore(); const userStore = useUserStore();
const { lampAuthorization, lampClientId, lampClientSecret } = getAppEnvConfig(); const { lampAuthorization, lampClientId, lampClientSecret } = getAppEnvConfig();

View File

@@ -1,54 +1,41 @@
import type { Result } from '@/types'; import type { Result } from '@/types';
import axios, { isAxiosError, type AxiosError, type AxiosInstance, type AxiosRequestConfig, type AxiosResponse, type CreateAxiosDefaults, type InternalAxiosRequestConfig } from 'axios'; import axios, { isAxiosError, type AxiosError, type AxiosRequestConfig, type AxiosResponse, type CreateAxiosDefaults, type InternalAxiosRequestConfig } from 'axios';
export type Response<T> = [err: AxiosError | null, data: T | null, resp: Result<T> | null]; export type HttpResponse<T> = [err: AxiosError | null, data: T | null, resp: Result<T> | null];
export interface RequestOptions extends CreateAxiosDefaults { export interface HttpRequestOptions extends CreateAxiosDefaults {
requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>; requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
responseInterceptor?: (resp: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>; responseInterceptor?: (resp: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>;
responseErrorInterceptor?: (error: any) => any; responseErrorInterceptor?: (error: any) => any;
} }
export class RequestClient { export const createHttpClient = (config?: HttpRequestOptions) => {
private instance: AxiosInstance; const defaultRequestInterceptor = (config: InternalAxiosRequestConfig) => config;
const defaultResponseInterceptor = (response: AxiosResponse) => response;
constructor(config?: RequestOptions) { const defaultResponseErrorInterceptor = (error: any) => {
this.instance = axios.create(config); if (isAxiosError(error)) {
if (error.status === 401) {
const requestInterceptor = config?.requestInterceptor ?? RequestClient.defaultRequestInterceptor; // 处理 401 错误
const responseInterceptor = config?.responseInterceptor ?? RequestClient.defaultResponseInterceptor; }
const responseErrorInterceptor = config?.responseErrorInterceptor ?? RequestClient.defaultResponseErrorInterceptor; if (error.status === 404) {
// 处理 404 错误
this.instance.interceptors.request.use(requestInterceptor); }
this.instance.interceptors.response.use(responseInterceptor, responseErrorInterceptor);
}
private static defaultRequestInterceptor(config: InternalAxiosRequestConfig) {
return config;
}
private static defaultResponseInterceptor(response: AxiosResponse) {
return response;
}
private static defaultResponseErrorInterceptor(error: any) {
const err = error as AxiosError;
if (err.status === 401) {
}
if (err.status === 404) {
} }
return Promise.reject(error); return Promise.reject(error);
} };
public get requestInstance(): AxiosInstance { const requestInterceptor = config?.requestInterceptor ?? defaultRequestInterceptor;
return this.instance; const responseInterceptor = config?.responseInterceptor ?? defaultResponseInterceptor;
} const responseErrorInterceptor = config?.responseErrorInterceptor ?? defaultResponseErrorInterceptor;
get<T>(url: string, options?: AxiosRequestConfig & { retRaw?: boolean }): Promise<Response<T>> { const instance = axios.create(config);
instance.interceptors.request.use(requestInterceptor);
instance.interceptors.response.use(responseInterceptor, responseErrorInterceptor);
const httpGet = <T>(url: string, options?: AxiosRequestConfig & { retRaw?: boolean }): Promise<HttpResponse<T>> => {
const { retRaw, ...reqConfig } = options ?? {}; const { retRaw, ...reqConfig } = options ?? {};
return new Promise((resolve) => { return new Promise((resolve) => {
this.instance instance
.get(url, { .get(url, {
...reqConfig, ...reqConfig,
}) })
@@ -64,12 +51,12 @@ export class RequestClient {
resolve([err as AxiosError, null, null]); resolve([err as AxiosError, null, null]);
}); });
}); });
} };
post<T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>> & { retRaw?: boolean; upload?: boolean }): Promise<Response<T>> { const httpPost = <T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>> & { retRaw?: boolean; upload?: boolean }): Promise<HttpResponse<T>> => {
const { retRaw, upload, ...reqConfig } = options ?? {}; const { retRaw, upload, ...reqConfig } = options ?? {};
return new Promise((resolve) => { return new Promise((resolve) => {
this.instance instance
.post(url, data, { headers: { 'content-type': upload ? 'multipart/form-data' : 'application/json' }, ...reqConfig }) .post(url, data, { headers: { 'content-type': upload ? 'multipart/form-data' : 'application/json' }, ...reqConfig })
.then((res) => { .then((res) => {
const resData = res.data; const resData = res.data;
@@ -83,12 +70,12 @@ export class RequestClient {
resolve([err as AxiosError, null, null]); resolve([err as AxiosError, null, null]);
}); });
}); });
} };
put<T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<Response<T>> { const httpPut = <T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<HttpResponse<T>> => {
const reqConfig = options ?? {}; const reqConfig = options ?? {};
return new Promise((resolve) => { return new Promise((resolve) => {
this.instance instance
.put<Result<T>>(url, data, { ...reqConfig }) .put<Result<T>>(url, data, { ...reqConfig })
.then((res) => { .then((res) => {
resolve([null, res.data.data, res.data]); resolve([null, res.data.data, res.data]);
@@ -97,12 +84,12 @@ export class RequestClient {
resolve([err as AxiosError, null, null]); resolve([err as AxiosError, null, null]);
}); });
}); });
} };
delete<T>(url: string, idList: string[], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<Response<T>> { const httpDelete = <T>(url: string, idList: string[], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<HttpResponse<T>> => {
const reqConfig = options ?? {}; const reqConfig = options ?? {};
return new Promise((resolve) => { return new Promise((resolve) => {
this.instance instance
.delete<Result<T>>(url, { ...reqConfig, data: idList }) .delete<Result<T>>(url, { ...reqConfig, data: idList })
.then((res) => { .then((res) => {
resolve([null, res.data.data, res.data]); resolve([null, res.data.data, res.data]);
@@ -111,11 +98,21 @@ export class RequestClient {
resolve([err as AxiosError, null, null]); resolve([err as AxiosError, null, null]);
}); });
}); });
} };
}
return {
get clientInstance() {
return instance;
},
get: httpGet,
post: httpPost,
put: httpPut,
delete: httpDelete,
};
};
// 从响应中解析出数据 // 从响应中解析出数据
export const unwrapResponse = <T>(resp: Response<T>) => { export const unwrapResponse = <T>(resp: HttpResponse<T>) => {
const [err, data, result] = resp; const [err, data, result] = resp;
// 如果 err 存在说明有 http 错误,那么直接抛出错误, // 如果 err 存在说明有 http 错误,那么直接抛出错误,

View File

@@ -4,5 +4,5 @@ export * from './download';
export * from './env'; export * from './env';
export * from './format-duration'; export * from './format-duration';
export * from './random-num'; export * from './random-num';
export * from './request-client'; export * from './http-client';
export * from './sleep'; export * from './sleep';