fix: fix the preference problem,close #8, close #9

This commit is contained in:
vince
2024-07-04 22:14:51 +08:00
parent 51f682a726
commit 53d37ee882
14 changed files with 77 additions and 314 deletions

View File

@@ -1,127 +0,0 @@
import type { AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { AxiosCanceler } from './canceler';
describe('axiosCanceler', () => {
let axiosCanceler: AxiosCanceler;
beforeEach(() => {
axiosCanceler = new AxiosCanceler();
});
it('should generate a unique request key', () => {
const config: AxiosRequestConfig = {
data: { name: 'test' },
method: 'get',
params: { id: 1 },
url: '/test',
};
const requestKey = axiosCanceler.getRequestKey(config);
expect(requestKey).toBe('get:/test:{"id":1}:{"name":"test"}');
});
it('should add a request and create an AbortController', () => {
const config: InternalAxiosRequestConfig = {
data: { name: 'test' },
method: 'get',
params: { id: 1 },
url: '/test',
} as InternalAxiosRequestConfig;
const updatedConfig = axiosCanceler.addRequest(config);
expect(updatedConfig.signal).toBeInstanceOf(AbortSignal);
});
it('should cancel an existing request if a duplicate is added', () => {
const config: InternalAxiosRequestConfig = {
data: { name: 'test' },
method: 'get',
params: { id: 1 },
url: '/test',
} as InternalAxiosRequestConfig;
axiosCanceler.addRequest(config);
const controller = axiosCanceler.pending.get(
'get:/test:{"id":1}:{"name":"test"}',
);
expect(controller).toBeDefined();
if (controller) {
const spy = vi.spyOn(controller, 'abort');
axiosCanceler.addRequest(config);
expect(spy).toHaveBeenCalled();
}
});
it('should remove a request', () => {
const config: AxiosRequestConfig = {
data: { name: 'test' },
method: 'get',
params: { id: 1 },
url: '/test',
};
axiosCanceler.addRequest(config as InternalAxiosRequestConfig);
axiosCanceler.removeRequest(config);
expect(axiosCanceler.pending.size).toBe(0);
});
it('should remove all pending requests', () => {
const config1: InternalAxiosRequestConfig = {
data: { name: 'test1' },
method: 'get',
params: { id: 1 },
url: '/test1',
} as InternalAxiosRequestConfig;
const config2: InternalAxiosRequestConfig = {
data: { name: 'test2' },
method: 'get',
params: { id: 2 },
url: '/test2',
} as InternalAxiosRequestConfig;
axiosCanceler.addRequest(config1);
axiosCanceler.addRequest(config2);
axiosCanceler.removeAllPending();
expect(axiosCanceler.pending.size).toBe(0);
});
it('should handle empty config gracefully', () => {
const config = {} as InternalAxiosRequestConfig;
const updatedConfig = axiosCanceler.addRequest(config);
expect(updatedConfig.signal).toBeInstanceOf(AbortSignal);
});
it('should handle undefined params and data gracefully', () => {
const config: InternalAxiosRequestConfig = {
method: 'get',
url: '/test',
} as InternalAxiosRequestConfig;
const requestKey = axiosCanceler.getRequestKey(config);
expect(requestKey).toBe('get:/test:{}:{}');
});
it('should not abort if no controller exists for the request key', () => {
const config: InternalAxiosRequestConfig = {
data: { name: 'test' },
method: 'get',
params: { id: 1 },
url: '/test',
} as InternalAxiosRequestConfig;
const requestKey = axiosCanceler.getRequestKey(config);
const spy = vi.spyOn(AbortController.prototype, 'abort');
axiosCanceler.addRequest(config);
axiosCanceler.pending.delete(requestKey);
axiosCanceler.addRequest(config);
expect(spy).not.toHaveBeenCalled();
});
});

View File

@@ -1,52 +0,0 @@
import type {
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios';
class AxiosCanceler {
public pending: Map<string, AbortController> = new Map();
// 添加请求
public addRequest(
config: InternalAxiosRequestConfig,
): InternalAxiosRequestConfig {
const requestKey = this.getRequestKey(config);
if (this.pending.has(requestKey)) {
// 如果存在相同的请求,取消前一个请求
const controller = this.pending.get(requestKey);
controller?.abort();
}
// 创建新的AbortController并添加到pending中
const controller = new AbortController();
config.signal = controller.signal;
this.pending.set(requestKey, controller);
return config;
}
// 生成请求的唯一标识
public getRequestKey(config: AxiosRequestConfig): string {
const { data = {}, method, params = {}, url } = config;
return `${method}:${url}:${JSON.stringify(params)}:${JSON.stringify(data)}`;
}
/**
* 清除所有等待中的请求
*/
public removeAllPending(): void {
for (const [, abortController] of this.pending) {
abortController?.abort();
}
this.pending.clear();
}
// 移除请求
public removeRequest(config: AxiosRequestConfig | AxiosResponse): void {
const requestKey = this.getRequestKey(config);
this.pending.delete(requestKey);
}
}
export { AxiosCanceler };

View File

@@ -12,7 +12,6 @@ import { merge } from '@vben-core/toolkit';
import axios from 'axios';
import { AxiosCanceler } from './modules/canceler';
import { FileDownloader } from './modules/downloader';
import { InterceptorManager } from './modules/interceptor';
import { FileUploader } from './modules/uploader';
@@ -97,8 +96,6 @@ class RequestClient {
private setupInterceptors() {
// 默认拦截器
this.setupAuthorizationInterceptor();
// 设置取消请求的拦截器
this.setupCancelerInterceptor();
}
/**
@@ -168,28 +165,6 @@ class RequestClient {
throw error.response ? error.response.data : error;
}
}
public setupCancelerInterceptor() {
const axiosCanceler = new AxiosCanceler();
// 注册取消重复请求的请求拦截器
this.addRequestInterceptor((config: InternalAxiosRequestConfig) => {
return axiosCanceler.addRequest(config);
}, this.errorHandler);
// 注册移除请求的响应拦截器
this.addResponseInterceptor(
(response: AxiosResponse) => {
axiosCanceler.removeRequest(response);
return response;
},
(error) => {
if (error.config) {
axiosCanceler.removeRequest(error.config);
}
return Promise.reject(error);
},
);
}
}
export { RequestClient };