Skip to content

Commit

Permalink
feat(优化): requestConfig、customConfig提升到类成员属性,各个方法不再接收配置参数;全局配置由privat…
Browse files Browse the repository at this point in the history
…e改为protected;StatusHandler接收requestConfig;request方法的requestConfig的ts类型里剔除掉几个属性
  • Loading branch information
mengxinssfd committed Apr 25, 2022
1 parent baf8811 commit 4224e31
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 48 deletions.
4 changes: 2 additions & 2 deletions __test__/AxiosRequestTemplate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ describe('AxiosWrapper', () => {
statusHandlers: { '200': (res) => res },
},
// 改为post,无效;
// methodFactory优先级更高,除了method,url,data其他的axios配置优先级都是这里的高
{ method: 'post' },
// methodFactory的method优先级更高,除了method,url,data其他的axios配置优先级都是这里的高
{ method: 'post' } as any,
);
expect(res1).toEqual({
data: { code: 200, data: { username: 'get', id: 1 }, msg: 'success' },
Expand Down
4 changes: 2 additions & 2 deletions __test__/Primary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export default class Primary extends AxiosRequestTemplate {
super({ baseURL: 'http://test.test' }, { statusHandlers });
}

protected handleRequestData(data: {}, requestConfig) {
super.handleRequestData({ ...data, token: 123 }, requestConfig);
protected handleRequestData(data: {}) {
super.handleRequestData({ ...data, token: 123 });
}

protected setInterceptors() {
Expand Down
12 changes: 4 additions & 8 deletions __test__/retry.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
import axios, { AxiosError } from 'axios';
import { AxiosRequestTemplate, CustomConfig, ResType } from '../src';

jest.mock('axios');
Expand Down Expand Up @@ -30,13 +30,9 @@ describe('retry', () => {
class RetryTemp<CC extends RetryConfig> extends AxiosRequestTemplate<CC> {
private retryMap = new Map<string, number>();

protected handleError(
requestConfig: AxiosRequestConfig,
customConfig: RetryConfig,
e: AxiosError<ResType<any>>,
): any {
if (customConfig.retry === undefined)
return super.handleError(requestConfig, customConfig as CC, e);
protected handleError(e: AxiosError<ResType<any>>): any {
const { requestConfig, customConfig } = this;
if (customConfig.retry === undefined) return super.handleError(e);
const key = this.generateRequestKey(requestConfig);
const value = this.retryMap.get(key) || 0;
if (value && value >= customConfig.retry) {
Expand Down
68 changes: 33 additions & 35 deletions src/AxiosRequestTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,24 @@ import { CustomCacheConfig } from './types';

// 使用模板方法模式处理axios请求, 具体类可实现protected方法替换掉原有方法
export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
// 为了提高子类的拓展性,子类可以访问并使用该实例,但如果没必要不要去访问该axios实例
// 实例
protected axiosIns!: AxiosInstance;
protected cache!: Cache<AxiosPromise>;

// cancel函数缓存
protected readonly cancelerMap = new Map<CancelToken, Canceler>();
protected readonly tagCancelMap = new Map<string, CancelToken[]>();

// 当前配置
protected requestConfig!: AxiosRequestConfig;
protected customConfig!: CC;

cancelCurrentRequest?: Canceler;

constructor(
private globalRequestConfig: AxiosRequestConfig = {},
private globalCustomConfig = {} as CC,
// 全局配置
protected globalRequestConfig: AxiosRequestConfig = {},
protected globalCustomConfig = {} as CC,
) {
this.init();
this.setInterceptors();
Expand All @@ -45,11 +52,7 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
}

// 转换数据结构为ResType
protected handleResponse<T>(
requestConfig: AxiosRequestConfig,
customConfig: CC,
response: AxiosResponse,
): ResType<T> {
protected handleResponse<T>(response: AxiosResponse): ResType<T> {
return response?.data as ResType;
}
// 获取拦截器
Expand All @@ -65,10 +68,8 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
}

// 设置取消handler
protected handleCanceler(
requestConfig: AxiosRequestConfig,
customConfig: CustomConfig,
): Function {
protected handleCanceler(): Function {
const { requestConfig, customConfig } = this;
const { cancel, token } = axios.CancelToken.source();
requestConfig.cancelToken = token;
const tag = customConfig.tag;
Expand Down Expand Up @@ -132,8 +133,9 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
config.cache = this.mergeCacheConfig(customConfig.cache);
return config;
}
// 处理请求的数据
protected handleRequestData(data: {}, requestConfig: AxiosRequestConfig) {
// 处理请求用的数据
protected handleRequestData(data: {}) {
const requestConfig = this.requestConfig;
if (String(requestConfig.method).toLowerCase() === 'get') {
requestConfig.params = data;
return;
Expand All @@ -144,8 +146,8 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
protected handleStatus<T>(
response: AxiosResponse<ResType<any>>,
data: ResType<any>,
customConfig: CC,
): Promise<ResType<T>> {
const { customConfig, requestConfig } = this;
const code = data?.code ?? 'default';
const handlers = {
default: (res, data, customConfig) => (customConfig.returnRes ? res : data),
Expand All @@ -154,11 +156,12 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
};

const statusHandler = handlers[code] || handlers.default;
return statusHandler(response, data, customConfig);
return statusHandler(response, data, customConfig, requestConfig);
}

// 请求
protected execRequest(requestConfig: AxiosRequestConfig, customConfig: CC) {
protected execRequest() {
const { requestConfig, customConfig } = this;
// 使用缓存
const cacheConfig = customConfig.cache as CustomCacheConfig;
const useCache = cacheConfig.enable;
Expand All @@ -180,12 +183,11 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {

// 模板方法,最终请求所使用的方法。
// 可子类覆盖,如非必要不建议子类覆盖
request<T = never>(url: string, data?: {}): Promise<ResType<T>>;
request<T = never, RC extends boolean = false>(
url: string,
data?: {},
customConfig?: DynamicCustomConfig<CC, RC>,
requestConfig?: AxiosRequestConfig,
requestConfig?: Omit<AxiosRequestConfig, 'data' | 'params'>,
): Promise<RC extends true ? AxiosResponse<ResType<T>> : ResType<T>>;
async request<T>(
url: string,
Expand All @@ -194,42 +196,38 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
requestConfig: AxiosRequestConfig = {},
): Promise<any> {
// 1、处理配置
requestConfig = this.handleRequestConfig(url, requestConfig);
this.handleRequestData(data, requestConfig);
customConfig = this.handleCustomConfig(customConfig);
this.requestConfig = this.handleRequestConfig(url, requestConfig);
this.handleRequestData(data);
this.customConfig = this.handleCustomConfig(customConfig);
// 2、处理cancel handler
const clearCanceler = this.handleCanceler(requestConfig, customConfig);
const clearCanceler = this.handleCanceler();
try {
// 3、请求
const response: AxiosResponse = await this.execRequest(requestConfig, customConfig);
const response: AxiosResponse = await this.execRequest();
// 清理cancel
clearCanceler();
// 4、请求结果数据结构处理
const data = this.handleResponse<T>(requestConfig, customConfig, response);
const data = this.handleResponse<T>(response);
// 5、状态码处理,并返回结果
return this.handleStatus<T>(response, data, customConfig);
return this.handleStatus<T>(response, data);
} catch (error: any) {
const e = error as AxiosError<ResType<any>>;
// 清理cancel
clearCanceler();
// 错误处理
const response = e.response as AxiosResponse<ResType<any>>;
// 4、请求结果数据结构处理
const data = this.handleResponse<T>(requestConfig, customConfig, response);
const data = this.handleResponse<T>(response);
if (data && data.code !== undefined) {
// 5、状态码处理,并返回结果
return this.handleStatus<T>(response, data, customConfig);
return this.handleStatus<T>(response, data);
}
// 如未命中error处理 则再次抛出error
return this.handleError(requestConfig, customConfig, e);
return this.handleError(e);
}
}

protected handleError(
requestConfig: AxiosRequestConfig,
customConfig: CC,
e: AxiosError<ResType<any>>,
): any {
protected handleError(e: AxiosError<ResType<any>>): any {
throw e;
}

Expand Down Expand Up @@ -257,7 +255,7 @@ export class AxiosRequestTemplate<CC extends CustomConfig = CustomConfig> {
url: string,
data?: {},
customConfig?: DynamicCustomConfig<CC, RC>,
requestConfig?: AxiosRequestConfig,
requestConfig?: Omit<AxiosRequestConfig, 'data' | 'params' | 'method'>,
) => this.request<T, RC>(url, data, customConfig, { ...requestConfig, method });
}
}
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { AxiosResponse } from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

export type StatusHandler<CC extends CustomConfig> = (
res: AxiosResponse<ResType<any>>,
data: ResType<any>,
customConfig: CC,
requestConfig: AxiosRequestConfig,
) => any;

// StatusHandlers
Expand Down

0 comments on commit 4224e31

Please sign in to comment.