Skip to content

Commit

Permalink
refactor(projects): axios封装完成
Browse files Browse the repository at this point in the history
  • Loading branch information
honghuangdc committed Nov 22, 2021
1 parent 451c754 commit 03b398a
Show file tree
Hide file tree
Showing 21 changed files with 332 additions and 145 deletions.
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#请求的环境
VITE_HTTP_ENV=DEV
#请求地址
VITE_HTTP_URL=http://192.168.100.43:8201
VITE_HTTP_URL=https://test.aisuit.com.cn
15 changes: 15 additions & 0 deletions src/interface/business/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** 数据字典 */
export interface Dictionary {
/** 字典名字 */
label: string;
/** 要素名字(一级指标) */
charactorLabel: string;
/** 要素下的指标key(二级指标) */
indicatorKey: string;
/** 要素下的指标名字(二级指标) */
indicatorLabel: string;
/** 备注 */
remark: string;
/** 指标公式 */
formula: string;
}
1 change: 1 addition & 0 deletions src/interface/business/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './auth';
export * from './demo';
15 changes: 15 additions & 0 deletions src/interface/common/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** 数据字典 */
export interface ResponseDictionary {
/** 字典名字 */
modelName: string;
/** 要素名字(一级指标) */
modelCharactorName: string;
/** 要素下的指标key(二级指标) */
modelIndicator: string;
/** 要素下的指标名字(二级指标) */
modelIndicatorName: string;
/** 备注 */
remarks: string;
/** 指标公式 */
formula: string;
}
2 changes: 2 additions & 0 deletions src/interface/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './system';
export * from './route';
export * from './service';
export * from './api';
50 changes: 50 additions & 0 deletions src/interface/common/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* 请求服务的错误类型:
* - axios: axios错误:网络错误, 请求超时, 默认的兜底错误
* - http: 请求成功,响应的状态码非200的错误
* - backend: 请求成功,响应的状态码为200,由后端定义的业务错误
*/
export type RequestServiceErrorType = 'axios' | 'http' | 'backend';

/** 请求服务的错误 */
export interface RequestServiceError {
/** 请求服务的错误类型 */
type: RequestServiceErrorType;
/** 错误码 */
code: string | number;
/** 错误信息 */
msg: string;
}

/** 后端接口返回的类型结构 */
export interface BackendServiceResult {
/** 状态码 */
code: number;
/** 接口数据 */
data: any;
/** 接口消息 */
message: string;
}

/** 自定义的请求成功结果 */
export interface CustomSuccessRequestResult<ResponseData> {
/** 请求错误 */
error: null;
/** 请求数据 */
data: ResponseData;
/** 网络状态 */
networkStatus: boolean;
}

/** 自定义的请求失败结果 */
export interface CustomFailRequestResult {
/** 请求错误 */
error: RequestServiceError;
/** 请求数据 */
data: null;
/** 网络状态 */
networkStatus: boolean;
}

/** 自定义的请求结果 */
export type CustomRequestResult<ResponseData> = CustomSuccessRequestResult<ResponseData> | CustomFailRequestResult;
8 changes: 0 additions & 8 deletions src/service/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +0,0 @@
import { request } from '../request';

/**
* 获取数据字典
*/
export async function fetchDictionary(keyword: string) {
await request.post('/ehe/model/getByIndicator', { indiCatorName: keyword });
}
File renamed without changes.
27 changes: 27 additions & 0 deletions src/service/api/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { ResponseDictionary, Dictionary } from '@/interface';
import { request, resultMiddleware } from '../request';
import { fecthDictionaryMiddleware } from '../middleware';

// 接口示例

/**
* 获取数据字典(不加middleware处理)
* @param keyword - 关键词
*/
export function fetchDictionary(keyword: string) {
return request.post<ResponseDictionary[]>('/emoss-entropy/ehe/model/getByIndicator', {
indiCatorName: keyword
});
}

/**
* 获取数据字典(加middleware处理)
* @param keyword - 关键词
*/
export async function fetchDictionaryWithMiddleware(keyword: string) {
const res = await request.post<ResponseDictionary[]>('/emoss-entropy/ehe/model/getByIndicator', {
indiCatorName: keyword
});

return resultMiddleware<Dictionary[]>(fecthDictionaryMiddleware, [res]);
}
2 changes: 1 addition & 1 deletion src/service/api/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './auth';
export * from './demo';
1 change: 0 additions & 1 deletion src/service/middleware/auth.ts

This file was deleted.

23 changes: 23 additions & 0 deletions src/service/middleware/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ResponseDictionary, Dictionary } from '@/interface';

export function fecthDictionaryMiddleware(data: ResponseDictionary[]): Dictionary[] {
return data.map(item => {
const {
modelName: label,
modelCharactorName: charactorLabel,
modelIndicator: indicatorKey,
modelIndicatorName: indicatorLabel,
remarks: remark,
formula
} = item;

return {
label,
charactorLabel,
indicatorKey,
indicatorLabel,
remark,
formula
};
});
}
2 changes: 1 addition & 1 deletion src/service/middleware/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './auth';
export * from './demo';
49 changes: 18 additions & 31 deletions src/service/request/axios/instance.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
import axios from 'axios';
import type { AxiosRequestConfig, AxiosInstance, AxiosError, CancelTokenStatic } from 'axios';
import { getToken } from '@/utils';
import { transformRequestData, handleAxiosError, handleResponseError } from '../helpers';

interface StatusConfig {
/** 表明请求状态的属性key */
statusKey: string;
/** 请求信息的属性key */
msgKey: string;
/** 成功状态的状态码 */
successCode: string | number;
}
import type { BackendServiceResult } from '@/interface';
import { transformRequestData, handleAxiosError, handleResponseError, handleBackendError } from '../helpers';

/**
* 封装axios请求类
* @author Soybean<honghuangdc@gmail.com> 2021-03-13
* @author Soybean<honghuangdc@gmail.com>
*/
export default class CustomAxiosInstance {
instance: AxiosInstance;

cancelToken: CancelTokenStatic;
private backendSuccessCode = 200;

private statusConfig: StatusConfig = {
statusKey: 'code',
msgKey: 'message',
successCode: 200
};
cancelToken: CancelTokenStatic;

constructor(axiosConfig: AxiosRequestConfig) {
this.instance = axios.create(axiosConfig);
Expand All @@ -40,35 +28,34 @@ export default class CustomAxiosInstance {
const handleConfig = { ...config };
if (handleConfig.headers) {
// 数据转换
handleConfig.data = await transformRequestData(handleConfig.data, handleConfig.headers['Content-Type']);
const contentType = handleConfig.headers['Content-Type'];
handleConfig.data = await transformRequestData(handleConfig.data, contentType);
// 设置token
handleConfig.headers.Authorization = getToken();
}
return handleConfig;
},
(error: AxiosError) => {
handleAxiosError(error);
(axiosError: AxiosError) => {
const error = handleAxiosError(axiosError);
return Promise.reject(error);
}
);
this.instance.interceptors.response.use(
response => {
const { status, data } = response;
const { statusKey, msgKey, successCode } = this.statusConfig;
const { status } = response;
if (status === 200 || status < 300 || status === 304) {
const responseData = data as any;
if (responseData[statusKey] === successCode) {
return Promise.resolve(responseData.data);
const backendServiceResult = response.data as BackendServiceResult;
if (backendServiceResult.code === this.backendSuccessCode) {
return Promise.resolve(backendServiceResult.data);
}
window.$message?.error(responseData[msgKey]);
return Promise.reject(responseData[msgKey]);
const error = handleBackendError(backendServiceResult);
return Promise.reject(error);
}
const error = { response };
handleResponseError(response);
const error = handleResponseError(response);
return Promise.reject(error);
},
(error: AxiosError) => {
handleAxiosError(error);
(axiosError: AxiosError) => {
const error = handleAxiosError(axiosError);
return Promise.reject(error);
}
);
Expand Down
92 changes: 38 additions & 54 deletions src/service/request/axios/request.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios';

type ResponseSuccess = [null, any];
type ResponseFail = [any, null];
import type { RequestServiceError, CustomSuccessRequestResult, CustomFailRequestResult } from '@/interface';

/**
* 封装各个请求方法及结果处理的类
* @author Soybean<honghuangdc@gmail.com> 2021-03-15
* @class Request
* @author Soybean<honghuangdc@gmail.com>
*/
export default class Request {
instance: AxiosInstance;
Expand All @@ -15,64 +12,51 @@ export default class Request {
this.instance = instance;
}

static successHandler(response: AxiosResponse) {
const result: ResponseSuccess = [null, response];
return result;
static successHandler<ResponseData>(response: AxiosResponse) {
const successResult: CustomSuccessRequestResult<ResponseData> = {
data: response as unknown as ResponseData,
error: null,
networkStatus: window.navigator.onLine
};

return successResult;
}

static failHandler(error: any) {
const result: ResponseFail = [error, null];
return result;
static failHandler(error: RequestServiceError) {
const failResult: CustomFailRequestResult = {
data: null,
error,
networkStatus: window.navigator.onLine
};

return failResult;
}

get(url: string, config?: AxiosRequestConfig) {
return this.instance.get(url, config).then(Request.successHandler).catch(Request.failHandler);
get<ResponseData>(url: string, config?: AxiosRequestConfig) {
return this.instance
.get(url, config)
.then(res => Request.successHandler<ResponseData>(res))
.catch(Request.failHandler);
}

post(url: string, data?: any, config?: AxiosRequestConfig) {
return this.instance.post(url, data, config).then(Request.successHandler).catch(Request.failHandler);
post<ResponseData>(url: string, data?: any, config?: AxiosRequestConfig) {
return this.instance
.post(url, data, config)
.then(res => Request.successHandler<ResponseData>(res))
.catch(Request.failHandler);
}

put(url: string, data?: any, config?: AxiosRequestConfig) {
return this.instance.put(url, data, config).then(Request.successHandler).catch(Request.failHandler);
put<ResponseData>(url: string, data?: any, config?: AxiosRequestConfig) {
return this.instance
.put(url, data, config)
.then(res => Request.successHandler<ResponseData>(res))
.catch(Request.failHandler);
}

delete(url: string, config?: AxiosRequestConfig) {
return this.instance.delete(url, config).then(Request.successHandler).catch(Request.failHandler);
delete<ResponseData>(url: string, config?: AxiosRequestConfig) {
return this.instance
.delete(url, config)
.then(res => Request.successHandler<ResponseData>(res))
.catch(Request.failHandler);
}
}

// import type { AxiosRequestConfig, AxiosInstance } from 'axios';
// import { useBoolean } from '@/hooks';

// type RequestMethod = 'get' | 'post' | 'put' | 'delete';

// interface RequestParam<ResponseData> {
// /** axios实例 */
// instance: AxiosInstance;
// /** 请求地址 */
// url: string;
// /** 请求方法 */
// method?: RequestMethod;
// /** axios请求配置 */
// axiosConfig?: AxiosRequestConfig;
// /** 请求结果的数据判断是否为空的函数 */
// responseDataEmptyFunc?: (data: ResponseData) => boolean;
// /** 全局请求错误时是否弹出消息 */
// showErrorMsg?: boolean;
// }

// /**
// * 请求函数hooks
// * @param requestParam - 请求函数的参数
// * @param url - 请求地址
// * @param axiosConfig
// */
// export default function useRequest<ResponseData>(requestParam: RequestParam<ResponseData>) {
// /** 网络状况 */
// const { bool: networkStatus, setBool: setNetworkStatus } = useBoolean(window.navigator.onLine);
// /** 是否正在请求 */
// const { bool: isFetching, setBool: setIsFetching } = useBoolean();
// /** 响应的结果数据是否为空 */
// const { bool: isEmpty, setBool: setIsEmpty } = useBoolean();
// }
14 changes: 13 additions & 1 deletion src/service/request/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
/** 请求超时时间 */
export const REQUEST_TIMEOUT = 60 * 1000;

/** 默认的请求错误文本 */
/** 错误信息的显示时间 */
export const ERROR_MSG_DURATION = 3 * 1000;

/** 兜底的请求错误code */
export const DEFAULT_REQUEST_ERROR_CODE = 'DEFAULT';
/** 兜底的请求错误文本 */
export const DEFAULT_REQUEST_ERROR_MSG = '请求错误~';

/** 请求超时的错误code(为固定值:ECONNABORTED) */
export const REQUEST_TIMEOUT_CODE = 'ECONNABORTED';
/** 请求超时的错误文本 */
export const REQUEST_TIMEOUT_MSG = '请求超时~';

/** 网络不可用的code */
export const NETWORK_ERROR_CODE = 'NETWORK_ERROR';
/** 网络不可用的错误文本 */
export const NETWORK_ERROR_MSG = '网络不可用~';

Expand All @@ -25,3 +34,6 @@ export const ERROR_STATUS = {
504: '504: 网关超时~',
505: '505: http版本不支持该请求~'
};

/** 不弹出错误信息的code */
export const NO_ERROR_MSG_CODE: (string | number)[] = [];
Loading

1 comment on commit 03b398a

@vercel
Copy link

@vercel vercel bot commented on 03b398a Nov 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.