Skip to content

Commit 2ca323b

Browse files
committed
refactor(projects): refactor code organization
1 parent 7ff4f52 commit 2ca323b

File tree

7 files changed

+112
-87
lines changed

7 files changed

+112
-87
lines changed

src/index.ts

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
import axios from 'axios';
22
import type { AxiosRequestConfig, AxiosInstance } from 'axios';
33
import {
4-
CONTENT_TYPE,
4+
createDefaultRequestConfig,
5+
getRequestHeaderContentType,
56
transformRequestData,
67
isHttpSuccess,
78
handleAxiosError,
89
handleHttpError,
910
handleBackendError
1011
} from './shared';
11-
import type { ContentTypeValue } from './shared';
12-
import type { RequestConfig } from './types';
12+
import type { RequestConfig, RequiredRequestConfig } from './types';
1313

1414
class Request {
1515
axiosInstance: AxiosInstance;
1616

17-
requestConfig: RequestConfig;
17+
requestConfig: RequiredRequestConfig;
1818

19-
constructor(axiosConfig: AxiosRequestConfig, requestConfig: RequestConfig) {
19+
constructor(axiosConfig: AxiosRequestConfig, requestConfig?: RequestConfig) {
2020
this.axiosInstance = axios.create(axiosConfig);
2121
this.setInterceptor();
2222

23-
this.requestConfig = requestConfig;
23+
this.requestConfig = createDefaultRequestConfig(requestConfig);
2424
}
2525

2626
/** 设置请求拦截器 */
2727
setInterceptor() {
2828
this.axiosInstance.interceptors.request.use(
2929
async config => {
30-
const conf = { ...config };
30+
const conf: AxiosRequestConfig = { ...config };
3131

32-
if (conf.headers) {
33-
// 数据转换
34-
const contentType = (conf.headers['Content-Type'] || CONTENT_TYPE.json) as ContentTypeValue;
35-
conf.data = await transformRequestData(config.data, contentType);
36-
}
32+
const contentType = getRequestHeaderContentType(conf);
33+
34+
conf.data = await transformRequestData(config.data, contentType);
35+
36+
const handledConf = await this.requestConfig.onRequest(conf);
3737

38-
Object.assign(conf, this.requestConfig.onRequest(conf));
38+
Object.assign(conf, handledConf);
3939

4040
return conf;
4141
},
@@ -68,21 +68,15 @@ class Request {
6868
}
6969
}
7070

71-
export function createRequest(axiosConfig: AxiosRequestConfig, requestConfig?: Partial<RequestConfig>) {
72-
const configs: RequestConfig = {
73-
codeKey: 'code',
74-
dataKey: 'data',
75-
msgKey: 'message',
76-
successCode: 200,
77-
onRequest: config => config,
78-
onBackendSuccess: responseData => {
79-
const { codeKey, successCode } = configs;
80-
return responseData[codeKey] === successCode;
81-
}
82-
};
83-
Object.assign(configs, requestConfig);
84-
85-
const request = new Request(axiosConfig, configs);
71+
/**
72+
* 创建请求
73+
* @param axiosConfig axios配置
74+
* @param requestConfig 请求配置
75+
* @param isRaw 是否返回原始的axios实例, (默认返回自定义的请求实例)
76+
*/
77+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
78+
export function createRequest(axiosConfig: AxiosRequestConfig, requestConfig?: RequestConfig, isRaw = false) {
79+
const request = new Request(axiosConfig, requestConfig);
8680

8781
return request.axiosInstance;
8882
}

src/shared/common.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
import type { AxiosRequestConfig, AxiosInstance } from 'axios';
2+
import { CONTENT_TYPE, type ContentTypeValue } from './constant';
3+
import type { RequestConfig, RequiredRequestConfig } from '../types';
4+
5+
export function createDefaultRequestConfig(requestConfig?: RequestConfig) {
6+
const configs: RequiredRequestConfig = {
7+
codeKey: 'code',
8+
dataKey: 'data',
9+
msgKey: 'message',
10+
onRequest: async config => config,
11+
onBackendSuccess: responseData => {
12+
const BACKEND_SUCCESS_CODE = 200;
13+
const { codeKey } = configs;
14+
return responseData[codeKey] === BACKEND_SUCCESS_CODE;
15+
},
16+
onBackendFail: async () => {},
17+
onError: async ({ error }) => {
18+
window.console.log(`code: ${error.code}, msg: ${error.msg}`);
19+
}
20+
};
21+
22+
Object.assign(configs, requestConfig);
23+
24+
return configs;
25+
}
26+
27+
export function getRequestHeaderContentType(config: AxiosRequestConfig) {
28+
const contentType = (config?.headers?.['Content-Type'] || CONTENT_TYPE.json) as ContentTypeValue;
29+
30+
return contentType;
31+
}
32+
133
/**
234
* http是否请求成功
335
* @param status http状态码
@@ -6,3 +38,6 @@ export function isHttpSuccess(status: number) {
638
const isSuccessCode = status >= 200 && status < 300;
739
return isSuccessCode || status === 304;
840
}
41+
42+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
43+
export function getCustomRequestInstance(instance: AxiosInstance) {}

src/shared/constant.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export const NETWORK_ERROR_CODE = 'NETWORK_ERROR';
3333
/** 网络不可用的错误文本 */
3434
export const NETWORK_ERROR_MSG = '网络不可用~';
3535

36+
export const BLANK_AXIOS_ERROR_CODE = '';
37+
3638
/** 请求不成功各种状态的错误 */
3739
export const ERROR_STATUS = {
3840
400: '400: 请求出现语法错误~',

src/shared/error.ts

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,16 @@
1-
import type { AxiosError, AxiosResponse } from 'axios';
1+
import type { AxiosResponse } from 'axios';
22
import {
33
DEFAULT_REQUEST_ERROR_CODE,
44
DEFAULT_REQUEST_ERROR_MSG,
55
NETWORK_ERROR_CODE,
66
NETWORK_ERROR_MSG,
77
REQUEST_TIMEOUT_CODE,
88
REQUEST_TIMEOUT_MSG,
9+
BLANK_AXIOS_ERROR_CODE,
910
ERROR_STATUS
1011
} from './constant';
1112
import type { ErrorStatus } from './constant';
12-
import type { RequestConfig } from '../types';
13-
14-
/**
15-
* 请求的错误类型:
16-
* - axios: axios错误:网络错误, 请求超时, 默认的兜底错误
17-
* - http: 请求成功,响应的http状态码非200的错误
18-
* - backend: 请求成功,响应的http状态码为200,由后端定义的业务错误
19-
*/
20-
export type RequestErrorType = 'axios' | 'http' | 'backend';
21-
22-
type AxiosErrorCode =
23-
| 'ERR_FR_TOO_MANY_REDIRECTS'
24-
| 'ERR_BAD_OPTION_VALUE'
25-
| 'ERR_BAD_OPTION'
26-
| 'ERR_NETWORK'
27-
| 'ERR_DEPRECATED'
28-
| 'ERR_BAD_RESPONSE'
29-
| 'ERR_BAD_REQUEST'
30-
| 'ERR_NOT_SUPPORT'
31-
| 'ERR_INVALID_URL'
32-
| 'ERR_CANCELED'
33-
| 'ECONNABORTED'
34-
| 'ETIMEDOUT';
35-
36-
const BLANK_AXIOS_ERROR_CODE = '';
37-
38-
type RawError<T, D> = Pick<AxiosError<T, D>, 'message' | 'config' | 'response'> & {
39-
code: AxiosErrorCode | typeof BLANK_AXIOS_ERROR_CODE;
40-
request: XMLHttpRequest;
41-
};
42-
43-
interface CustomError {
44-
/** 请求服务的错误类型 */
45-
type: RequestErrorType;
46-
/** 错误码 */
47-
code: string | number;
48-
/** 错误信息 */
49-
msg: string;
50-
}
51-
52-
/** 请求错误 */
53-
interface RequestError<T, D> {
54-
/** 自定义的错误 */
55-
error: CustomError;
56-
/** 原始请求错误 */
57-
rawError: RawError<T, D>;
58-
}
13+
import type { CustomError, RawError, RequestError, RequestConfig } from '../types';
5914

6015
function updateCustomError(error: CustomError, update: Partial<CustomError>) {
6116
Object.assign(error, update);

src/shared/transform.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import qs from 'qs';
22
import FormData from 'form-data';
3+
import { isArray, isFile } from './typeof';
34
import { CONTENT_TYPE } from './constant';
45
import type { ContentTypeValue } from './constant';
56

@@ -59,12 +60,6 @@ async function transformFile(formData: FormData, key: string, file: File[] | Fil
5960
}
6061
}
6162

62-
function isArray<T extends any[]>(value: T | unknown): value is T {
63-
return Object.prototype.toString.call(value) === '[object Array]';
64-
}
65-
function isFile<T extends File>(value: T | unknown): value is T {
66-
return Object.prototype.toString.call(value) === '[object File]';
67-
}
6863
function isFileArray<T extends File[]>(value: T | unknown): value is T {
6964
return isArray(value) && value.length > 0 && isFile(value[0]);
7065
}

src/shared/typeof.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function isObject<T extends Record<string, unknown>>(value: T | unknown): value is T {
2+
return Object.prototype.toString.call(value) === '[object Object]';
3+
}
4+
5+
export function isArray<T extends any[]>(value: T | unknown): value is T {
6+
return Object.prototype.toString.call(value) === '[object Array]';
7+
}
8+
9+
export function isFile<T extends File>(value: T | unknown): value is T {
10+
return Object.prototype.toString.call(value) === '[object File]';
11+
}
12+
13+
export function isBlob<T extends Blob>(value: T | unknown): value is T {
14+
return Object.prototype.toString.call(value) === '[object Blob]';
15+
}
16+
17+
export function isArrayBuffer<T extends ArrayBuffer>(value: T | unknown): value is T {
18+
return Object.prototype.toString.call(value) === '[object ArrayBuffer]';
19+
}
20+
21+
export function isArrayBufferView<T extends ArrayBufferView>(value: T | unknown): value is T {
22+
return Object.prototype.toString.call(value) === '[object ArrayBufferView]';
23+
}

src/types/index.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,44 @@ export interface RequestConfig {
5656
dataKey: string;
5757
/** 表示后端消息的属性字段 */
5858
msgKey: string;
59-
/** 后端业务上定义的成功请求的状态 */
60-
successCode: number | string;
6159
/**
6260
* 请求前的钩子函数
6361
* @param config 请求配置
6462
* @example 可以对请求头进行操作,如设置Token
6563
*/
66-
onRequest(config: AxiosRequestConfig): AxiosRequestConfig;
64+
onRequest?: (config: AxiosRequestConfig) => Promise<AxiosRequestConfig>;
6765
/**
6866
* http请求成功情况下,后端业务上表示请求成功的处理
6967
* @param responseData 请求后的数据 (response.data)
7068
*/
71-
onBackendSuccess(responseData: any): boolean;
69+
onBackendSuccess?: (responseData: any) => boolean;
7270
/**
7371
* http请求成功情况下, 后端业务上表示请求失败的处理
7472
* @param response axios的相响应
7573
* @param axiosInstance axios实例
7674
*/
77-
onBackendFail?(response: AxiosResponse, axiosInstance: AxiosInstance): Promise<AxiosResponse | void>;
75+
onBackendFail?: (response: AxiosResponse, axiosInstance: AxiosInstance) => Promise<AxiosResponse | void>;
76+
/** 请求失败情况下,对错误进行处理,例如:进行错误信息展示 */
77+
onError?: <T, D>(error: RequestError<T, D>) => Promise<void>;
7878
}
79+
80+
export type RequiredRequestConfig = Required<RequestConfig>;
81+
82+
/** 自定义的请求成功结果 */
83+
export interface SuccessResponse<T> {
84+
/** 请求错误 */
85+
error: null;
86+
/** 请求数据 */
87+
data: T;
88+
}
89+
90+
/** 自定义的请求失败结果 */
91+
export interface FailedResponse<T> {
92+
/** 请求错误 */
93+
error: RequestError<T, any>;
94+
/** 请求数据 */
95+
data: null;
96+
}
97+
98+
/** 自定义的请求结果 */
99+
export type CustomResponse<T> = SuccessResponse<T> | FailedResponse<T>;

0 commit comments

Comments
 (0)