@taicode/common-base 1.0.2 → 1.1.0
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/README.md +121 -0
- package/package.json +21 -3
- package/source/catch/catch.test.ts +341 -0
- package/source/catch/catch.ts +35 -0
- package/source/catch/index.ts +1 -0
- package/source/color/color.test.ts +144 -0
- package/source/{utils/color/index.ts → color/color.ts} +7 -0
- package/source/color/index.ts +1 -0
- package/source/debounce/debounce.test.ts +179 -0
- package/source/debounce/debounce.ts +42 -0
- package/source/debounce/index.ts +1 -0
- package/source/disposer/disposer.test.ts +257 -0
- package/source/disposer/index.ts +1 -0
- package/source/error/error.test.ts +293 -0
- package/source/error/error.ts +38 -0
- package/source/error/index.ts +1 -0
- package/source/event-emitter/event-emitter.test.ts +247 -0
- package/source/{utils/event-emitter/index.ts → event-emitter/event-emitter.ts} +2 -0
- package/source/event-emitter/index.ts +1 -0
- package/source/index.ts +19 -0
- package/source/logger/index.ts +43 -0
- package/source/logger/logger.test.ts +36 -0
- package/source/number/index.ts +1 -0
- package/source/number/number.test.ts +60 -0
- package/source/object/index.ts +1 -0
- package/source/{utils/object/index.test.ts → object/object.test.ts} +8 -8
- package/source/string/index.ts +1 -0
- package/source/string/string.test.ts +98 -0
- package/source/throttle/index.ts +1 -0
- package/source/throttle/throttle.test.ts +228 -0
- package/source/throttle/throttle.ts +76 -0
- package/test-exports.js +6 -0
- package/tsconfig.json +16 -21
- package/vitest.config.ts +8 -0
- package/source/decorators/debounce.ts +0 -25
- package/source/utils/poller/index.test.ts +0 -62
- package/source/utils/poller/index.ts +0 -57
- package/source/utils/promise/index.test.ts +0 -38
- package/source/utils/promise/index.ts +0 -45
- /package/source/{utils/disposer → disposer}/disposer.ts +0 -0
- /package/source/{utils/number/index.ts → number/number.ts} +0 -0
- /package/source/{utils/object/index.ts → object/object.ts} +0 -0
- /package/source/{utils/string/index.ts → string/string.ts} +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
+
import { debounce, debounceFn } from './debounce'
|
|
3
|
+
|
|
4
|
+
describe('debounce', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.useFakeTimers()
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
vi.restoreAllMocks()
|
|
11
|
+
vi.useRealTimers()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('debounceFn', () => {
|
|
15
|
+
it('应该延迟函数执行', async () => {
|
|
16
|
+
const mockFn = vi.fn().mockResolvedValue('result')
|
|
17
|
+
const debouncedFn = debounceFn(mockFn, 100)
|
|
18
|
+
|
|
19
|
+
const promise = debouncedFn('arg1', 'arg2')
|
|
20
|
+
|
|
21
|
+
// 函数不应该立即执行
|
|
22
|
+
expect(mockFn).not.toHaveBeenCalled()
|
|
23
|
+
|
|
24
|
+
// 推进时间
|
|
25
|
+
vi.advanceTimersByTime(100)
|
|
26
|
+
await promise
|
|
27
|
+
|
|
28
|
+
expect(mockFn).toHaveBeenCalledOnce()
|
|
29
|
+
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('应该取消之前的调用', async () => {
|
|
33
|
+
const mockFn = vi.fn().mockResolvedValue('result')
|
|
34
|
+
const debouncedFn = debounceFn(mockFn, 100)
|
|
35
|
+
|
|
36
|
+
// 快速连续调用
|
|
37
|
+
debouncedFn('first')
|
|
38
|
+
debouncedFn('second')
|
|
39
|
+
const finalPromise = debouncedFn('third')
|
|
40
|
+
|
|
41
|
+
// 推进时间
|
|
42
|
+
vi.advanceTimersByTime(100)
|
|
43
|
+
await finalPromise
|
|
44
|
+
|
|
45
|
+
// 只应该执行最后一次调用
|
|
46
|
+
expect(mockFn).toHaveBeenCalledOnce()
|
|
47
|
+
expect(mockFn).toHaveBeenCalledWith('third')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('应该处理同步函数', async () => {
|
|
51
|
+
const mockFn = vi.fn().mockReturnValue('sync-result')
|
|
52
|
+
const debouncedFn = debounceFn(mockFn, 100)
|
|
53
|
+
|
|
54
|
+
const promise = debouncedFn('arg')
|
|
55
|
+
vi.advanceTimersByTime(100)
|
|
56
|
+
|
|
57
|
+
const result = await promise
|
|
58
|
+
expect(result).toBe('sync-result')
|
|
59
|
+
expect(mockFn).toHaveBeenCalledWith('arg')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('应该处理异步函数', async () => {
|
|
63
|
+
const mockFn = vi.fn().mockResolvedValue('async-result')
|
|
64
|
+
const debouncedFn = debounceFn(mockFn, 100)
|
|
65
|
+
|
|
66
|
+
const promise = debouncedFn('arg')
|
|
67
|
+
vi.advanceTimersByTime(100)
|
|
68
|
+
|
|
69
|
+
const result = await promise
|
|
70
|
+
expect(result).toBe('async-result')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('应该处理函数执行错误', async () => {
|
|
74
|
+
const error = new Error('Test error')
|
|
75
|
+
const mockFn = vi.fn().mockRejectedValue(error)
|
|
76
|
+
const debouncedFn = debounceFn(mockFn, 100)
|
|
77
|
+
|
|
78
|
+
const promise = debouncedFn('arg')
|
|
79
|
+
vi.advanceTimersByTime(100)
|
|
80
|
+
|
|
81
|
+
await expect(promise).rejects.toThrow('Test error')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('应该保持 this 上下文', async () => {
|
|
85
|
+
class TestClass {
|
|
86
|
+
value = 'test-value'
|
|
87
|
+
|
|
88
|
+
getValue() {
|
|
89
|
+
return this.value
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const instance = new TestClass()
|
|
94
|
+
const debouncedMethod = debounceFn(instance.getValue, 100)
|
|
95
|
+
|
|
96
|
+
const promise = debouncedMethod.call(instance)
|
|
97
|
+
vi.advanceTimersByTime(100)
|
|
98
|
+
|
|
99
|
+
const result = await promise
|
|
100
|
+
expect(result).toBe('test-value')
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
describe('debounce decorator', () => {
|
|
105
|
+
it('应该装饰类方法', async () => {
|
|
106
|
+
class TestClass {
|
|
107
|
+
callCount = 0
|
|
108
|
+
|
|
109
|
+
@debounce(100)
|
|
110
|
+
increment() {
|
|
111
|
+
this.callCount++
|
|
112
|
+
return this.callCount
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const instance = new TestClass()
|
|
117
|
+
|
|
118
|
+
// 快速连续调用
|
|
119
|
+
instance.increment()
|
|
120
|
+
instance.increment()
|
|
121
|
+
instance.increment()
|
|
122
|
+
|
|
123
|
+
// 推进时间
|
|
124
|
+
vi.advanceTimersByTime(100)
|
|
125
|
+
|
|
126
|
+
// 只应该执行一次
|
|
127
|
+
expect(instance.callCount).toBe(1)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('应该为每个实例独立工作', async () => {
|
|
131
|
+
class TestClass {
|
|
132
|
+
value = 0
|
|
133
|
+
|
|
134
|
+
@debounce(100)
|
|
135
|
+
async setValue(newValue: number) {
|
|
136
|
+
this.value = newValue
|
|
137
|
+
return this.value
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const instance1 = new TestClass()
|
|
142
|
+
const instance2 = new TestClass()
|
|
143
|
+
|
|
144
|
+
const promise1 = instance1.setValue(10)
|
|
145
|
+
const promise2 = instance2.setValue(20)
|
|
146
|
+
|
|
147
|
+
vi.advanceTimersByTime(100)
|
|
148
|
+
|
|
149
|
+
await Promise.all([promise1, promise2])
|
|
150
|
+
|
|
151
|
+
expect(instance1.value).toBe(10)
|
|
152
|
+
expect(instance2.value).toBe(20)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
it('应该处理带参数的方法', async () => {
|
|
156
|
+
class TestClass {
|
|
157
|
+
lastArgs: any[] = []
|
|
158
|
+
|
|
159
|
+
@debounce(100)
|
|
160
|
+
async saveArgs(...args: any[]) {
|
|
161
|
+
this.lastArgs = args
|
|
162
|
+
return args
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const instance = new TestClass()
|
|
167
|
+
|
|
168
|
+
instance.saveArgs(1, 2, 3)
|
|
169
|
+
instance.saveArgs(4, 5, 6)
|
|
170
|
+
const promise = instance.saveArgs(7, 8, 9)
|
|
171
|
+
|
|
172
|
+
vi.advanceTimersByTime(100)
|
|
173
|
+
const result = await promise
|
|
174
|
+
|
|
175
|
+
expect(result).toEqual([7, 8, 9])
|
|
176
|
+
expect(instance.lastArgs).toEqual([7, 8, 9])
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 防抖装饰器 - 基于 TC39 Stage 3 Decorators 提案
|
|
3
|
+
* 在最后一次调用后等待指定时间才执行函数
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// 通用防抖函数
|
|
7
|
+
export function debounceFn<T extends (...args: any[]) => any>(
|
|
8
|
+
fn: T,
|
|
9
|
+
wait: number
|
|
10
|
+
): T {
|
|
11
|
+
let timeout: ReturnType<typeof setTimeout> | null = null
|
|
12
|
+
|
|
13
|
+
function debounced(this: any, ...args: any[]) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
if (timeout) clearTimeout(timeout)
|
|
16
|
+
|
|
17
|
+
timeout = setTimeout(async () => {
|
|
18
|
+
try {
|
|
19
|
+
const result = await Promise.resolve(fn.apply(this, args))
|
|
20
|
+
resolve(result)
|
|
21
|
+
} catch (error) {
|
|
22
|
+
reject(error)
|
|
23
|
+
}
|
|
24
|
+
}, wait)
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return debounced as T
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// TC39 Stage 3 装饰器实现
|
|
32
|
+
export function debounce<T extends (...args: any[]) => any>(wait: number) {
|
|
33
|
+
return function (originalMethod: T, context: ClassMethodDecoratorContext): T {
|
|
34
|
+
// 每个实例独立
|
|
35
|
+
context.addInitializer(function () {
|
|
36
|
+
const self = this as any
|
|
37
|
+
const debouncedMethod = debounceFn(originalMethod.bind(self), wait)
|
|
38
|
+
self[context.name] = debouncedMethod
|
|
39
|
+
})
|
|
40
|
+
return originalMethod
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './debounce'
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
+
import { Disposer } from './disposer'
|
|
3
|
+
|
|
4
|
+
describe('Disposer', () => {
|
|
5
|
+
let disposer: Disposer
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
disposer = new Disposer()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
describe('addDisposer', () => {
|
|
12
|
+
it('应该能够添加清理函数', () => {
|
|
13
|
+
const cleanupFn = vi.fn()
|
|
14
|
+
|
|
15
|
+
expect(() => {
|
|
16
|
+
disposer.addDisposer(cleanupFn)
|
|
17
|
+
}).not.toThrow()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('应该能够添加多个清理函数', () => {
|
|
21
|
+
const cleanupFn1 = vi.fn()
|
|
22
|
+
const cleanupFn2 = vi.fn()
|
|
23
|
+
const cleanupFn3 = vi.fn()
|
|
24
|
+
|
|
25
|
+
disposer.addDisposer(cleanupFn1)
|
|
26
|
+
disposer.addDisposer(cleanupFn2)
|
|
27
|
+
disposer.addDisposer(cleanupFn3)
|
|
28
|
+
|
|
29
|
+
disposer.dispose()
|
|
30
|
+
|
|
31
|
+
expect(cleanupFn1).toHaveBeenCalledOnce()
|
|
32
|
+
expect(cleanupFn2).toHaveBeenCalledOnce()
|
|
33
|
+
expect(cleanupFn3).toHaveBeenCalledOnce()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('应该能够添加返回不同类型的清理函数', () => {
|
|
37
|
+
const voidFn = vi.fn(() => {})
|
|
38
|
+
const stringFn = vi.fn(() => 'cleanup result')
|
|
39
|
+
const numberFn = vi.fn(() => 42)
|
|
40
|
+
const promiseFn = vi.fn(() => Promise.resolve('async cleanup'))
|
|
41
|
+
|
|
42
|
+
disposer.addDisposer(voidFn)
|
|
43
|
+
disposer.addDisposer(stringFn)
|
|
44
|
+
disposer.addDisposer(numberFn)
|
|
45
|
+
disposer.addDisposer(promiseFn)
|
|
46
|
+
|
|
47
|
+
disposer.dispose()
|
|
48
|
+
|
|
49
|
+
expect(voidFn).toHaveBeenCalled()
|
|
50
|
+
expect(stringFn).toHaveBeenCalled()
|
|
51
|
+
expect(numberFn).toHaveBeenCalled()
|
|
52
|
+
expect(promiseFn).toHaveBeenCalled()
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe('dispose', () => {
|
|
57
|
+
it('应该执行所有清理函数', () => {
|
|
58
|
+
const cleanupFn1 = vi.fn()
|
|
59
|
+
const cleanupFn2 = vi.fn()
|
|
60
|
+
const cleanupFn3 = vi.fn()
|
|
61
|
+
|
|
62
|
+
disposer.addDisposer(cleanupFn1)
|
|
63
|
+
disposer.addDisposer(cleanupFn2)
|
|
64
|
+
disposer.addDisposer(cleanupFn3)
|
|
65
|
+
|
|
66
|
+
disposer.dispose()
|
|
67
|
+
|
|
68
|
+
expect(cleanupFn1).toHaveBeenCalledOnce()
|
|
69
|
+
expect(cleanupFn2).toHaveBeenCalledOnce()
|
|
70
|
+
expect(cleanupFn3).toHaveBeenCalledOnce()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('应该按添加顺序执行清理函数', () => {
|
|
74
|
+
const executionOrder: number[] = []
|
|
75
|
+
|
|
76
|
+
disposer.addDisposer(() => executionOrder.push(1))
|
|
77
|
+
disposer.addDisposer(() => executionOrder.push(2))
|
|
78
|
+
disposer.addDisposer(() => executionOrder.push(3))
|
|
79
|
+
|
|
80
|
+
disposer.dispose()
|
|
81
|
+
|
|
82
|
+
expect(executionOrder).toEqual([1, 2, 3])
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('应该处理清理函数中的错误', () => {
|
|
86
|
+
const workingFn1 = vi.fn()
|
|
87
|
+
const errorFn = vi.fn(() => {
|
|
88
|
+
throw new Error('Cleanup error')
|
|
89
|
+
})
|
|
90
|
+
const workingFn2 = vi.fn()
|
|
91
|
+
|
|
92
|
+
// 模拟 console.error
|
|
93
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
94
|
+
|
|
95
|
+
disposer.addDisposer(workingFn1)
|
|
96
|
+
disposer.addDisposer(errorFn)
|
|
97
|
+
disposer.addDisposer(workingFn2)
|
|
98
|
+
|
|
99
|
+
// dispose 不应该抛出错误
|
|
100
|
+
expect(() => {
|
|
101
|
+
disposer.dispose()
|
|
102
|
+
}).not.toThrow()
|
|
103
|
+
|
|
104
|
+
// 所有函数都应该被调用
|
|
105
|
+
expect(workingFn1).toHaveBeenCalled()
|
|
106
|
+
expect(errorFn).toHaveBeenCalled()
|
|
107
|
+
expect(workingFn2).toHaveBeenCalled()
|
|
108
|
+
|
|
109
|
+
// 错误应该被记录
|
|
110
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', expect.any(Error))
|
|
111
|
+
|
|
112
|
+
consoleSpy.mockRestore()
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('应该在执行后清空清理函数列表', () => {
|
|
116
|
+
const cleanupFn = vi.fn()
|
|
117
|
+
|
|
118
|
+
disposer.addDisposer(cleanupFn)
|
|
119
|
+
disposer.dispose()
|
|
120
|
+
|
|
121
|
+
expect(cleanupFn).toHaveBeenCalledOnce()
|
|
122
|
+
|
|
123
|
+
// 再次调用 dispose 不应该执行任何函数
|
|
124
|
+
disposer.dispose()
|
|
125
|
+
expect(cleanupFn).toHaveBeenCalledOnce()
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('应该能够在清空后重新添加清理函数', () => {
|
|
129
|
+
const firstCleanup = vi.fn()
|
|
130
|
+
const secondCleanup = vi.fn()
|
|
131
|
+
|
|
132
|
+
disposer.addDisposer(firstCleanup)
|
|
133
|
+
disposer.dispose()
|
|
134
|
+
|
|
135
|
+
disposer.addDisposer(secondCleanup)
|
|
136
|
+
disposer.dispose()
|
|
137
|
+
|
|
138
|
+
expect(firstCleanup).toHaveBeenCalledOnce()
|
|
139
|
+
expect(secondCleanup).toHaveBeenCalledOnce()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('应该在没有清理函数时安全执行', () => {
|
|
143
|
+
expect(() => {
|
|
144
|
+
disposer.dispose()
|
|
145
|
+
}).not.toThrow()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('应该能够多次调用 dispose', () => {
|
|
149
|
+
const cleanupFn = vi.fn()
|
|
150
|
+
|
|
151
|
+
disposer.addDisposer(cleanupFn)
|
|
152
|
+
|
|
153
|
+
disposer.dispose()
|
|
154
|
+
disposer.dispose()
|
|
155
|
+
disposer.dispose()
|
|
156
|
+
|
|
157
|
+
expect(cleanupFn).toHaveBeenCalledOnce()
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
describe('实际使用场景', () => {
|
|
162
|
+
it('应该能够清理事件监听器', () => {
|
|
163
|
+
const removeEventListener = vi.fn()
|
|
164
|
+
const unsubscribe = vi.fn()
|
|
165
|
+
|
|
166
|
+
disposer.addDisposer(removeEventListener)
|
|
167
|
+
disposer.addDisposer(unsubscribe)
|
|
168
|
+
|
|
169
|
+
disposer.dispose()
|
|
170
|
+
|
|
171
|
+
expect(removeEventListener).toHaveBeenCalled()
|
|
172
|
+
expect(unsubscribe).toHaveBeenCalled()
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('应该能够清理定时器', () => {
|
|
176
|
+
const clearTimeout = vi.fn()
|
|
177
|
+
const clearInterval = vi.fn()
|
|
178
|
+
|
|
179
|
+
disposer.addDisposer(() => clearTimeout(123))
|
|
180
|
+
disposer.addDisposer(() => clearInterval(456))
|
|
181
|
+
|
|
182
|
+
disposer.dispose()
|
|
183
|
+
|
|
184
|
+
expect(clearTimeout).toHaveBeenCalledWith(123)
|
|
185
|
+
expect(clearInterval).toHaveBeenCalledWith(456)
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it('应该能够清理资源连接', () => {
|
|
189
|
+
const closeConnection = vi.fn()
|
|
190
|
+
const releaseResource = vi.fn()
|
|
191
|
+
|
|
192
|
+
disposer.addDisposer(() => closeConnection())
|
|
193
|
+
disposer.addDisposer(() => releaseResource())
|
|
194
|
+
|
|
195
|
+
disposer.dispose()
|
|
196
|
+
|
|
197
|
+
expect(closeConnection).toHaveBeenCalled()
|
|
198
|
+
expect(releaseResource).toHaveBeenCalled()
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('应该与 EventEmitter 配合使用', () => {
|
|
202
|
+
// 模拟 EventEmitter 的使用
|
|
203
|
+
const mockEventEmitter = {
|
|
204
|
+
on: vi.fn().mockReturnValue(vi.fn()), // 返回 off 函数
|
|
205
|
+
cleanup: vi.fn()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const offFunction1 = mockEventEmitter.on('event1', vi.fn())
|
|
209
|
+
const offFunction2 = mockEventEmitter.on('event2', vi.fn())
|
|
210
|
+
|
|
211
|
+
disposer.addDisposer(offFunction1)
|
|
212
|
+
disposer.addDisposer(offFunction2)
|
|
213
|
+
disposer.addDisposer(() => mockEventEmitter.cleanup())
|
|
214
|
+
|
|
215
|
+
disposer.dispose()
|
|
216
|
+
|
|
217
|
+
expect(offFunction1).toHaveBeenCalled()
|
|
218
|
+
expect(offFunction2).toHaveBeenCalled()
|
|
219
|
+
expect(mockEventEmitter.cleanup).toHaveBeenCalled()
|
|
220
|
+
})
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
describe('错误处理', () => {
|
|
224
|
+
it('应该捕获并记录同步错误', () => {
|
|
225
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
226
|
+
const error = new Error('Sync error')
|
|
227
|
+
|
|
228
|
+
disposer.addDisposer(() => {
|
|
229
|
+
throw error
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
disposer.dispose()
|
|
233
|
+
|
|
234
|
+
expect(consoleSpy).toHaveBeenCalledWith('Error during cleanup:', error)
|
|
235
|
+
consoleSpy.mockRestore()
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it('应该处理不同类型的错误', () => {
|
|
239
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
240
|
+
|
|
241
|
+
disposer.addDisposer(() => {
|
|
242
|
+
throw new TypeError('Type error')
|
|
243
|
+
})
|
|
244
|
+
disposer.addDisposer(() => {
|
|
245
|
+
throw 'String error'
|
|
246
|
+
})
|
|
247
|
+
disposer.addDisposer(() => {
|
|
248
|
+
throw { message: 'Object error' }
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
disposer.dispose()
|
|
252
|
+
|
|
253
|
+
expect(consoleSpy).toHaveBeenCalledTimes(3)
|
|
254
|
+
consoleSpy.mockRestore()
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './disposer'
|