@taicode/common-base 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/output/catch/catch.d.ts +9 -0
- package/output/catch/catch.d.ts.map +1 -0
- package/output/catch/catch.js +26 -0
- package/output/catch/catch.test.d.ts +2 -0
- package/output/catch/catch.test.d.ts.map +1 -0
- package/output/catch/catch.test.js +258 -0
- package/output/catch/index.d.ts +2 -0
- package/output/catch/index.d.ts.map +1 -0
- package/output/catch/index.js +1 -0
- package/output/color/color.d.ts +6 -0
- package/output/color/color.d.ts.map +1 -0
- package/output/color/color.js +57 -0
- package/output/color/color.test.d.ts +2 -0
- package/output/color/color.test.d.ts.map +1 -0
- package/output/color/color.test.js +110 -0
- package/output/color/index.d.ts +2 -0
- package/output/color/index.d.ts.map +1 -0
- package/output/color/index.js +1 -0
- package/output/debounce/debounce.d.ts +7 -0
- package/output/debounce/debounce.d.ts.map +1 -0
- package/output/debounce/debounce.js +36 -0
- package/output/debounce/debounce.test.d.ts +2 -0
- package/output/debounce/debounce.test.d.ts.map +1 -0
- package/output/debounce/debounce.test.js +135 -0
- package/output/debounce/index.d.ts +2 -0
- package/output/debounce/index.d.ts.map +1 -0
- package/output/debounce/index.js +1 -0
- package/output/disposer/disposer.d.ts +6 -0
- package/output/disposer/disposer.d.ts.map +1 -0
- package/output/disposer/disposer.js +19 -0
- package/output/disposer/disposer.test.d.ts +2 -0
- package/output/disposer/disposer.test.d.ts.map +1 -0
- package/output/disposer/disposer.test.js +192 -0
- package/output/disposer/index.d.ts +2 -0
- package/output/disposer/index.d.ts.map +1 -0
- package/output/disposer/index.js +1 -0
- package/output/error/error.d.ts +23 -0
- package/output/error/error.d.ts.map +1 -0
- package/output/error/error.js +37 -0
- package/output/error/error.test.d.ts +2 -0
- package/output/error/error.test.d.ts.map +1 -0
- package/output/error/error.test.js +242 -0
- package/output/error/index.d.ts +2 -0
- package/output/error/index.d.ts.map +1 -0
- package/output/error/index.js +1 -0
- package/output/event-emitter/event-emitter.d.ts +33 -0
- package/output/event-emitter/event-emitter.d.ts.map +1 -0
- package/output/event-emitter/event-emitter.js +66 -0
- package/output/event-emitter/event-emitter.test.d.ts +2 -0
- package/output/event-emitter/event-emitter.test.d.ts.map +1 -0
- package/output/event-emitter/event-emitter.test.js +177 -0
- package/output/event-emitter/index.d.ts +2 -0
- package/output/event-emitter/index.d.ts.map +1 -0
- package/output/event-emitter/index.js +1 -0
- package/output/events/disposer.d.ts +6 -0
- package/output/events/disposer.d.ts.map +1 -0
- package/output/events/disposer.js +19 -0
- package/output/events/disposer.test.d.ts +2 -0
- package/output/events/disposer.test.d.ts.map +1 -0
- package/output/events/disposer.test.js +192 -0
- package/output/events/event-emitter.d.ts +33 -0
- package/output/events/event-emitter.d.ts.map +1 -0
- package/output/events/event-emitter.js +66 -0
- package/output/events/event-emitter.test.d.ts +2 -0
- package/output/events/event-emitter.test.d.ts.map +1 -0
- package/output/events/event-emitter.test.js +213 -0
- package/output/events/index.d.ts +3 -0
- package/output/events/index.d.ts.map +1 -0
- package/output/events/index.js +3 -0
- package/output/index.d.ts +11 -0
- package/output/index.d.ts.map +1 -0
- package/output/index.js +15 -0
- package/output/logger/index.d.ts +18 -0
- package/output/logger/index.d.ts.map +1 -0
- package/output/logger/index.js +34 -0
- package/output/logger/logger.test.d.ts +2 -0
- package/output/logger/logger.test.d.ts.map +1 -0
- package/output/logger/logger.test.js +33 -0
- package/output/number/index.d.ts +2 -0
- package/output/number/index.d.ts.map +1 -0
- package/output/number/index.js +1 -0
- package/output/number/number.d.ts +2 -0
- package/output/number/number.d.ts.map +1 -0
- package/output/number/number.js +23 -0
- package/output/number/number.test.d.ts +2 -0
- package/output/number/number.test.d.ts.map +1 -0
- package/output/number/number.test.js +50 -0
- package/output/object/index.d.ts +2 -0
- package/output/object/index.d.ts.map +1 -0
- package/output/object/index.js +1 -0
- package/output/object/object.d.ts +7 -0
- package/output/object/object.d.ts.map +1 -0
- package/output/object/object.js +27 -0
- package/output/object/object.test.d.ts +2 -0
- package/output/object/object.test.d.ts.map +1 -0
- package/output/object/object.test.js +42 -0
- package/output/service/index.d.ts +2 -0
- package/output/service/index.d.ts.map +1 -0
- package/output/service/index.js +1 -0
- package/output/service/service.d.ts +6 -0
- package/output/service/service.d.ts.map +1 -0
- package/output/service/service.js +3 -0
- package/output/string/index.d.ts +2 -0
- package/output/string/index.d.ts.map +1 -0
- package/output/string/index.js +1 -0
- package/output/string/string.d.ts +3 -0
- package/output/string/string.d.ts.map +1 -0
- package/output/string/string.js +9 -0
- package/output/string/string.test.d.ts +2 -0
- package/output/string/string.test.d.ts.map +1 -0
- package/output/string/string.test.js +77 -0
- package/output/throttle/index.d.ts +2 -0
- package/output/throttle/index.d.ts.map +1 -0
- package/output/throttle/index.js +1 -0
- package/output/throttle/throttle.d.ts +12 -0
- package/output/throttle/throttle.d.ts.map +1 -0
- package/output/throttle/throttle.js +55 -0
- package/output/throttle/throttle.test.d.ts +2 -0
- package/output/throttle/throttle.test.d.ts.map +1 -0
- package/output/throttle/throttle.test.js +177 -0
- package/package.json +4 -1
- package/source/catch/catch.test.ts +0 -341
- package/source/catch/catch.ts +0 -35
- package/source/catch/index.ts +0 -1
- package/source/color/color.test.ts +0 -144
- package/source/color/color.ts +0 -73
- package/source/color/index.ts +0 -1
- package/source/debounce/debounce.test.ts +0 -179
- package/source/debounce/debounce.ts +0 -42
- package/source/debounce/index.ts +0 -1
- package/source/disposer/disposer.test.ts +0 -257
- package/source/disposer/disposer.ts +0 -20
- package/source/disposer/index.ts +0 -1
- package/source/error/error.test.ts +0 -293
- package/source/error/error.ts +0 -38
- package/source/error/index.ts +0 -1
- package/source/event-emitter/event-emitter.test.ts +0 -247
- package/source/event-emitter/event-emitter.ts +0 -79
- package/source/event-emitter/index.ts +0 -1
- package/source/index.ts +0 -19
- package/source/logger/index.ts +0 -43
- package/source/logger/logger.test.ts +0 -36
- package/source/number/index.ts +0 -1
- package/source/number/number.test.ts +0 -60
- package/source/number/number.ts +0 -25
- package/source/object/index.ts +0 -1
- package/source/object/object.test.ts +0 -54
- package/source/object/object.ts +0 -29
- package/source/string/index.ts +0 -1
- package/source/string/string.test.ts +0 -98
- package/source/string/string.ts +0 -9
- package/source/throttle/index.ts +0 -1
- package/source/throttle/throttle.test.ts +0 -228
- package/source/throttle/throttle.ts +0 -76
- package/test-exports.js +0 -6
- package/tsconfig.json +0 -98
- package/vitest.config.ts +0 -8
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { debounce, debounceFn } from './debounce';
|
|
3
|
+
describe('debounce', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.useFakeTimers();
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.restoreAllMocks();
|
|
9
|
+
vi.useRealTimers();
|
|
10
|
+
});
|
|
11
|
+
describe('debounceFn', () => {
|
|
12
|
+
it('应该延迟函数执行', async () => {
|
|
13
|
+
const mockFn = vi.fn().mockResolvedValue('result');
|
|
14
|
+
const debouncedFn = debounceFn(mockFn, 100);
|
|
15
|
+
const promise = debouncedFn('arg1', 'arg2');
|
|
16
|
+
// 函数不应该立即执行
|
|
17
|
+
expect(mockFn).not.toHaveBeenCalled();
|
|
18
|
+
// 推进时间
|
|
19
|
+
vi.advanceTimersByTime(100);
|
|
20
|
+
await promise;
|
|
21
|
+
expect(mockFn).toHaveBeenCalledOnce();
|
|
22
|
+
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
|
|
23
|
+
});
|
|
24
|
+
it('应该取消之前的调用', async () => {
|
|
25
|
+
const mockFn = vi.fn().mockResolvedValue('result');
|
|
26
|
+
const debouncedFn = debounceFn(mockFn, 100);
|
|
27
|
+
// 快速连续调用
|
|
28
|
+
debouncedFn('first');
|
|
29
|
+
debouncedFn('second');
|
|
30
|
+
const finalPromise = debouncedFn('third');
|
|
31
|
+
// 推进时间
|
|
32
|
+
vi.advanceTimersByTime(100);
|
|
33
|
+
await finalPromise;
|
|
34
|
+
// 只应该执行最后一次调用
|
|
35
|
+
expect(mockFn).toHaveBeenCalledOnce();
|
|
36
|
+
expect(mockFn).toHaveBeenCalledWith('third');
|
|
37
|
+
});
|
|
38
|
+
it('应该处理同步函数', async () => {
|
|
39
|
+
const mockFn = vi.fn().mockReturnValue('sync-result');
|
|
40
|
+
const debouncedFn = debounceFn(mockFn, 100);
|
|
41
|
+
const promise = debouncedFn('arg');
|
|
42
|
+
vi.advanceTimersByTime(100);
|
|
43
|
+
const result = await promise;
|
|
44
|
+
expect(result).toBe('sync-result');
|
|
45
|
+
expect(mockFn).toHaveBeenCalledWith('arg');
|
|
46
|
+
});
|
|
47
|
+
it('应该处理异步函数', async () => {
|
|
48
|
+
const mockFn = vi.fn().mockResolvedValue('async-result');
|
|
49
|
+
const debouncedFn = debounceFn(mockFn, 100);
|
|
50
|
+
const promise = debouncedFn('arg');
|
|
51
|
+
vi.advanceTimersByTime(100);
|
|
52
|
+
const result = await promise;
|
|
53
|
+
expect(result).toBe('async-result');
|
|
54
|
+
});
|
|
55
|
+
it('应该处理函数执行错误', async () => {
|
|
56
|
+
const error = new Error('Test error');
|
|
57
|
+
const mockFn = vi.fn().mockRejectedValue(error);
|
|
58
|
+
const debouncedFn = debounceFn(mockFn, 100);
|
|
59
|
+
const promise = debouncedFn('arg');
|
|
60
|
+
vi.advanceTimersByTime(100);
|
|
61
|
+
await expect(promise).rejects.toThrow('Test error');
|
|
62
|
+
});
|
|
63
|
+
it('应该保持 this 上下文', async () => {
|
|
64
|
+
class TestClass {
|
|
65
|
+
value = 'test-value';
|
|
66
|
+
getValue() {
|
|
67
|
+
return this.value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const instance = new TestClass();
|
|
71
|
+
const debouncedMethod = debounceFn(instance.getValue, 100);
|
|
72
|
+
const promise = debouncedMethod.call(instance);
|
|
73
|
+
vi.advanceTimersByTime(100);
|
|
74
|
+
const result = await promise;
|
|
75
|
+
expect(result).toBe('test-value');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('debounce decorator', () => {
|
|
79
|
+
it('应该装饰类方法', async () => {
|
|
80
|
+
class TestClass {
|
|
81
|
+
callCount = 0;
|
|
82
|
+
@debounce(100)
|
|
83
|
+
increment() {
|
|
84
|
+
this.callCount++;
|
|
85
|
+
return this.callCount;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const instance = new TestClass();
|
|
89
|
+
// 快速连续调用
|
|
90
|
+
instance.increment();
|
|
91
|
+
instance.increment();
|
|
92
|
+
instance.increment();
|
|
93
|
+
// 推进时间
|
|
94
|
+
vi.advanceTimersByTime(100);
|
|
95
|
+
// 只应该执行一次
|
|
96
|
+
expect(instance.callCount).toBe(1);
|
|
97
|
+
});
|
|
98
|
+
it('应该为每个实例独立工作', async () => {
|
|
99
|
+
class TestClass {
|
|
100
|
+
value = 0;
|
|
101
|
+
@debounce(100)
|
|
102
|
+
async setValue(newValue) {
|
|
103
|
+
this.value = newValue;
|
|
104
|
+
return this.value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const instance1 = new TestClass();
|
|
108
|
+
const instance2 = new TestClass();
|
|
109
|
+
const promise1 = instance1.setValue(10);
|
|
110
|
+
const promise2 = instance2.setValue(20);
|
|
111
|
+
vi.advanceTimersByTime(100);
|
|
112
|
+
await Promise.all([promise1, promise2]);
|
|
113
|
+
expect(instance1.value).toBe(10);
|
|
114
|
+
expect(instance2.value).toBe(20);
|
|
115
|
+
});
|
|
116
|
+
it('应该处理带参数的方法', async () => {
|
|
117
|
+
class TestClass {
|
|
118
|
+
lastArgs = [];
|
|
119
|
+
@debounce(100)
|
|
120
|
+
async saveArgs(...args) {
|
|
121
|
+
this.lastArgs = args;
|
|
122
|
+
return args;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const instance = new TestClass();
|
|
126
|
+
instance.saveArgs(1, 2, 3);
|
|
127
|
+
instance.saveArgs(4, 5, 6);
|
|
128
|
+
const promise = instance.saveArgs(7, 8, 9);
|
|
129
|
+
vi.advanceTimersByTime(100);
|
|
130
|
+
const result = await promise;
|
|
131
|
+
expect(result).toEqual([7, 8, 9]);
|
|
132
|
+
expect(instance.lastArgs).toEqual([7, 8, 9]);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/debounce/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './debounce';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disposer.d.ts","sourceRoot":"","sources":["../../source/disposer/disposer.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ;IACnB,OAAO,CAAC,gBAAgB,CAAyB;IAGjD,WAAW,CAAC,SAAS,EAAE,MAAM,OAAO,GAAG,IAAI;IAK3C,OAAO,IAAI,IAAI;CAUhB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class Disposer {
|
|
2
|
+
cleanupFunctions = [];
|
|
3
|
+
// 添加清理函数
|
|
4
|
+
addDisposer(cleanupFn) {
|
|
5
|
+
this.cleanupFunctions.push(cleanupFn);
|
|
6
|
+
}
|
|
7
|
+
// 执行所有清理函数
|
|
8
|
+
dispose() {
|
|
9
|
+
for (const cleanupFn of this.cleanupFunctions) {
|
|
10
|
+
try {
|
|
11
|
+
cleanupFn();
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error('Error during cleanup:', error);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
this.cleanupFunctions = []; // 清空清理函数列表
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disposer.test.d.ts","sourceRoot":"","sources":["../../source/disposer/disposer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Disposer } from './disposer';
|
|
3
|
+
describe('Disposer', () => {
|
|
4
|
+
let disposer;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
disposer = new Disposer();
|
|
7
|
+
});
|
|
8
|
+
describe('addDisposer', () => {
|
|
9
|
+
it('应该能够添加清理函数', () => {
|
|
10
|
+
const cleanupFn = vi.fn();
|
|
11
|
+
expect(() => {
|
|
12
|
+
disposer.addDisposer(cleanupFn);
|
|
13
|
+
}).not.toThrow();
|
|
14
|
+
});
|
|
15
|
+
it('应该能够添加多个清理函数', () => {
|
|
16
|
+
const cleanupFn1 = vi.fn();
|
|
17
|
+
const cleanupFn2 = vi.fn();
|
|
18
|
+
const cleanupFn3 = vi.fn();
|
|
19
|
+
disposer.addDisposer(cleanupFn1);
|
|
20
|
+
disposer.addDisposer(cleanupFn2);
|
|
21
|
+
disposer.addDisposer(cleanupFn3);
|
|
22
|
+
disposer.dispose();
|
|
23
|
+
expect(cleanupFn1).toHaveBeenCalledOnce();
|
|
24
|
+
expect(cleanupFn2).toHaveBeenCalledOnce();
|
|
25
|
+
expect(cleanupFn3).toHaveBeenCalledOnce();
|
|
26
|
+
});
|
|
27
|
+
it('应该能够添加返回不同类型的清理函数', () => {
|
|
28
|
+
const voidFn = vi.fn(() => { });
|
|
29
|
+
const stringFn = vi.fn(() => 'cleanup result');
|
|
30
|
+
const numberFn = vi.fn(() => 42);
|
|
31
|
+
const promiseFn = vi.fn(() => Promise.resolve('async cleanup'));
|
|
32
|
+
disposer.addDisposer(voidFn);
|
|
33
|
+
disposer.addDisposer(stringFn);
|
|
34
|
+
disposer.addDisposer(numberFn);
|
|
35
|
+
disposer.addDisposer(promiseFn);
|
|
36
|
+
disposer.dispose();
|
|
37
|
+
expect(voidFn).toHaveBeenCalled();
|
|
38
|
+
expect(stringFn).toHaveBeenCalled();
|
|
39
|
+
expect(numberFn).toHaveBeenCalled();
|
|
40
|
+
expect(promiseFn).toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('dispose', () => {
|
|
44
|
+
it('应该执行所有清理函数', () => {
|
|
45
|
+
const cleanupFn1 = vi.fn();
|
|
46
|
+
const cleanupFn2 = vi.fn();
|
|
47
|
+
const cleanupFn3 = vi.fn();
|
|
48
|
+
disposer.addDisposer(cleanupFn1);
|
|
49
|
+
disposer.addDisposer(cleanupFn2);
|
|
50
|
+
disposer.addDisposer(cleanupFn3);
|
|
51
|
+
disposer.dispose();
|
|
52
|
+
expect(cleanupFn1).toHaveBeenCalledOnce();
|
|
53
|
+
expect(cleanupFn2).toHaveBeenCalledOnce();
|
|
54
|
+
expect(cleanupFn3).toHaveBeenCalledOnce();
|
|
55
|
+
});
|
|
56
|
+
it('应该按添加顺序执行清理函数', () => {
|
|
57
|
+
const executionOrder = [];
|
|
58
|
+
disposer.addDisposer(() => executionOrder.push(1));
|
|
59
|
+
disposer.addDisposer(() => executionOrder.push(2));
|
|
60
|
+
disposer.addDisposer(() => executionOrder.push(3));
|
|
61
|
+
disposer.dispose();
|
|
62
|
+
expect(executionOrder).toEqual([1, 2, 3]);
|
|
63
|
+
});
|
|
64
|
+
it('应该处理清理函数中的错误', () => {
|
|
65
|
+
const workingFn1 = vi.fn();
|
|
66
|
+
const errorFn = vi.fn(() => {
|
|
67
|
+
throw new Error('Cleanup error');
|
|
68
|
+
});
|
|
69
|
+
const workingFn2 = vi.fn();
|
|
70
|
+
// 模拟 console.error
|
|
71
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
72
|
+
disposer.addDisposer(workingFn1);
|
|
73
|
+
disposer.addDisposer(errorFn);
|
|
74
|
+
disposer.addDisposer(workingFn2);
|
|
75
|
+
// dispose 不应该抛出错误
|
|
76
|
+
expect(() => {
|
|
77
|
+
disposer.dispose();
|
|
78
|
+
}).not.toThrow();
|
|
79
|
+
// 所有函数都应该被调用
|
|
80
|
+
expect(workingFn1).toHaveBeenCalled();
|
|
81
|
+
expect(errorFn).toHaveBeenCalled();
|
|
82
|
+
expect(workingFn2).toHaveBeenCalled();
|
|
83
|
+
// 错误应该被记录
|
|
84
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', expect.any(Error));
|
|
85
|
+
consoleSpy.mockRestore();
|
|
86
|
+
});
|
|
87
|
+
it('应该在执行后清空清理函数列表', () => {
|
|
88
|
+
const cleanupFn = vi.fn();
|
|
89
|
+
disposer.addDisposer(cleanupFn);
|
|
90
|
+
disposer.dispose();
|
|
91
|
+
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
92
|
+
// 再次调用 dispose 不应该执行任何函数
|
|
93
|
+
disposer.dispose();
|
|
94
|
+
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
95
|
+
});
|
|
96
|
+
it('应该能够在清空后重新添加清理函数', () => {
|
|
97
|
+
const firstCleanup = vi.fn();
|
|
98
|
+
const secondCleanup = vi.fn();
|
|
99
|
+
disposer.addDisposer(firstCleanup);
|
|
100
|
+
disposer.dispose();
|
|
101
|
+
disposer.addDisposer(secondCleanup);
|
|
102
|
+
disposer.dispose();
|
|
103
|
+
expect(firstCleanup).toHaveBeenCalledOnce();
|
|
104
|
+
expect(secondCleanup).toHaveBeenCalledOnce();
|
|
105
|
+
});
|
|
106
|
+
it('应该在没有清理函数时安全执行', () => {
|
|
107
|
+
expect(() => {
|
|
108
|
+
disposer.dispose();
|
|
109
|
+
}).not.toThrow();
|
|
110
|
+
});
|
|
111
|
+
it('应该能够多次调用 dispose', () => {
|
|
112
|
+
const cleanupFn = vi.fn();
|
|
113
|
+
disposer.addDisposer(cleanupFn);
|
|
114
|
+
disposer.dispose();
|
|
115
|
+
disposer.dispose();
|
|
116
|
+
disposer.dispose();
|
|
117
|
+
expect(cleanupFn).toHaveBeenCalledOnce();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('实际使用场景', () => {
|
|
121
|
+
it('应该能够清理事件监听器', () => {
|
|
122
|
+
const removeEventListener = vi.fn();
|
|
123
|
+
const unsubscribe = vi.fn();
|
|
124
|
+
disposer.addDisposer(removeEventListener);
|
|
125
|
+
disposer.addDisposer(unsubscribe);
|
|
126
|
+
disposer.dispose();
|
|
127
|
+
expect(removeEventListener).toHaveBeenCalled();
|
|
128
|
+
expect(unsubscribe).toHaveBeenCalled();
|
|
129
|
+
});
|
|
130
|
+
it('应该能够清理定时器', () => {
|
|
131
|
+
const clearTimeout = vi.fn();
|
|
132
|
+
const clearInterval = vi.fn();
|
|
133
|
+
disposer.addDisposer(() => clearTimeout(123));
|
|
134
|
+
disposer.addDisposer(() => clearInterval(456));
|
|
135
|
+
disposer.dispose();
|
|
136
|
+
expect(clearTimeout).toHaveBeenCalledWith(123);
|
|
137
|
+
expect(clearInterval).toHaveBeenCalledWith(456);
|
|
138
|
+
});
|
|
139
|
+
it('应该能够清理资源连接', () => {
|
|
140
|
+
const closeConnection = vi.fn();
|
|
141
|
+
const releaseResource = vi.fn();
|
|
142
|
+
disposer.addDisposer(() => closeConnection());
|
|
143
|
+
disposer.addDisposer(() => releaseResource());
|
|
144
|
+
disposer.dispose();
|
|
145
|
+
expect(closeConnection).toHaveBeenCalled();
|
|
146
|
+
expect(releaseResource).toHaveBeenCalled();
|
|
147
|
+
});
|
|
148
|
+
it('应该与 EventEmitter 配合使用', () => {
|
|
149
|
+
// 模拟 EventEmitter 的使用
|
|
150
|
+
const mockEventEmitter = {
|
|
151
|
+
on: vi.fn().mockReturnValue(vi.fn()), // 返回 off 函数
|
|
152
|
+
cleanup: vi.fn()
|
|
153
|
+
};
|
|
154
|
+
const offFunction1 = mockEventEmitter.on('event1', vi.fn());
|
|
155
|
+
const offFunction2 = mockEventEmitter.on('event2', vi.fn());
|
|
156
|
+
disposer.addDisposer(offFunction1);
|
|
157
|
+
disposer.addDisposer(offFunction2);
|
|
158
|
+
disposer.addDisposer(() => mockEventEmitter.cleanup());
|
|
159
|
+
disposer.dispose();
|
|
160
|
+
expect(offFunction1).toHaveBeenCalled();
|
|
161
|
+
expect(offFunction2).toHaveBeenCalled();
|
|
162
|
+
expect(mockEventEmitter.cleanup).toHaveBeenCalled();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('错误处理', () => {
|
|
166
|
+
it('应该捕获并记录同步错误', () => {
|
|
167
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
168
|
+
const error = new Error('Sync error');
|
|
169
|
+
disposer.addDisposer(() => {
|
|
170
|
+
throw error;
|
|
171
|
+
});
|
|
172
|
+
disposer.dispose();
|
|
173
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', error);
|
|
174
|
+
consoleSpy.mockRestore();
|
|
175
|
+
});
|
|
176
|
+
it('应该处理不同类型的错误', () => {
|
|
177
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
178
|
+
disposer.addDisposer(() => {
|
|
179
|
+
throw new TypeError('Type error');
|
|
180
|
+
});
|
|
181
|
+
disposer.addDisposer(() => {
|
|
182
|
+
throw 'String error';
|
|
183
|
+
});
|
|
184
|
+
disposer.addDisposer(() => {
|
|
185
|
+
throw { message: 'Object error' };
|
|
186
|
+
});
|
|
187
|
+
disposer.dispose();
|
|
188
|
+
expect(consoleSpy).toHaveBeenCalledTimes(3);
|
|
189
|
+
consoleSpy.mockRestore();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/disposer/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './disposer';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface ErrorOptions {
|
|
2
|
+
cause?: unknown;
|
|
3
|
+
}
|
|
4
|
+
/** 用户可见的错误 */
|
|
5
|
+
export declare class UserError<T extends string> extends Error {
|
|
6
|
+
type: T;
|
|
7
|
+
message: string;
|
|
8
|
+
constructor(type: T, message: string, options?: ErrorOptions);
|
|
9
|
+
static is<T extends string>(error: unknown): error is UserError<T>;
|
|
10
|
+
}
|
|
11
|
+
/** 系统错误 */
|
|
12
|
+
export declare class SystemError<T extends string> extends Error {
|
|
13
|
+
type: T;
|
|
14
|
+
message: string;
|
|
15
|
+
constructor(type: T, message: string, options?: ErrorOptions);
|
|
16
|
+
static is<T extends string>(error: unknown): error is SystemError<T>;
|
|
17
|
+
}
|
|
18
|
+
export declare class UnknownError extends Error {
|
|
19
|
+
constructor(message: string, options?: ErrorOptions);
|
|
20
|
+
static is(error: unknown): boolean;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../source/error/error.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,cAAc;AACd,qBAAa,SAAS,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,KAAK;IACjC,IAAI,EAAE,CAAC;IAAS,OAAO,EAAE,MAAM;gBAA/B,IAAI,EAAE,CAAC,EAAS,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAK1E,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;CAGnE;AAED,WAAW;AACX,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,KAAK;IACnC,IAAI,EAAE,CAAC;IAAS,OAAO,EAAE,MAAM;gBAA/B,IAAI,EAAE,CAAC,EAAS,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAK1E,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,CAAC,CAAC;CAGrE;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAKnD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;CAGnC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** 用户可见的错误 */
|
|
2
|
+
export class UserError extends Error {
|
|
3
|
+
type;
|
|
4
|
+
message;
|
|
5
|
+
constructor(type, message, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.type = type;
|
|
8
|
+
this.message = message;
|
|
9
|
+
this.name = 'UserError';
|
|
10
|
+
}
|
|
11
|
+
static is(error) {
|
|
12
|
+
return error instanceof UserError;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** 系统错误 */
|
|
16
|
+
export class SystemError extends Error {
|
|
17
|
+
type;
|
|
18
|
+
message;
|
|
19
|
+
constructor(type, message, options) {
|
|
20
|
+
super(message, options);
|
|
21
|
+
this.type = type;
|
|
22
|
+
this.message = message;
|
|
23
|
+
this.name = 'SystemError';
|
|
24
|
+
}
|
|
25
|
+
static is(error) {
|
|
26
|
+
return error instanceof SystemError;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class UnknownError extends Error {
|
|
30
|
+
constructor(message, options) {
|
|
31
|
+
super(message, options);
|
|
32
|
+
this.name = 'UnknownError';
|
|
33
|
+
}
|
|
34
|
+
static is(error) {
|
|
35
|
+
return error instanceof UnknownError;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../../source/error/error.test.ts"],"names":[],"mappings":""}
|