@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
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach, MockedFunction } from 'vitest'
|
|
2
|
-
import { Poller } from './'
|
|
3
|
-
|
|
4
|
-
describe('Poller', () => {
|
|
5
|
-
let poller: Poller
|
|
6
|
-
let task: MockedFunction<() => Promise<void> | void>
|
|
7
|
-
const interval = 100 // 100ms 的间隔
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
task = vi.fn()
|
|
11
|
-
poller = new Poller(task, interval)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
poller.stop() // 确保每次测试后停止轮询
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('should start and stop the poller', async () => {
|
|
19
|
-
poller.start()
|
|
20
|
-
expect(poller['isRunning']).toBe(true)
|
|
21
|
-
|
|
22
|
-
poller.stop()
|
|
23
|
-
expect(poller['isRunning']).toBe(false)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('should execute the task at the specified interval', async () => {
|
|
27
|
-
poller.start()
|
|
28
|
-
await new Promise((resolve) => setTimeout(resolve, interval * 2)) // 等待两个间隔
|
|
29
|
-
|
|
30
|
-
expect(task).toHaveBeenCalledTimes(2) // 任务应该被执行两次
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should stop the poller and clear the timeout', async () => {
|
|
34
|
-
poller.start()
|
|
35
|
-
await new Promise((resolve) => setTimeout(resolve, interval / 2)) // 等待半个间隔
|
|
36
|
-
poller.stop()
|
|
37
|
-
|
|
38
|
-
expect(poller['timeoutId']).toBeUndefined() // 定时器应该被清除
|
|
39
|
-
expect(poller['resolveCurrentWait']).toBeUndefined() // resolve 函数应该被清除
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should handle task errors and continue polling', async () => {
|
|
43
|
-
const error = new Error('Task failed')
|
|
44
|
-
task.mockRejectedValueOnce(error) // 模拟任务第一次执行时出错
|
|
45
|
-
|
|
46
|
-
const consoleSpy = vi.spyOn(console, 'error') // 捕获 console.error 调用
|
|
47
|
-
|
|
48
|
-
poller.start()
|
|
49
|
-
await new Promise((resolve) => setTimeout(resolve, interval * 2)) // 等待两个间隔
|
|
50
|
-
|
|
51
|
-
expect(consoleSpy).toHaveBeenCalledWith('Task execution error:', error) // 应该捕获到错误
|
|
52
|
-
expect(task).toHaveBeenCalledTimes(2) // 任务应该被执行两次,即使第一次出错
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should stop the poller immediately when stop is called', async () => {
|
|
56
|
-
poller.start()
|
|
57
|
-
await new Promise((resolve) => setTimeout(resolve, interval / 2)) // 等待半个间隔
|
|
58
|
-
poller.stop()
|
|
59
|
-
|
|
60
|
-
expect(task).toHaveBeenCalledTimes(1) // 任务应该只被执行一次
|
|
61
|
-
})
|
|
62
|
-
})
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
export type PollerTask = () => Promise<void> | void
|
|
2
|
-
|
|
3
|
-
export class Poller {
|
|
4
|
-
private task: PollerTask // 需要执行的函数
|
|
5
|
-
private interval: number // 执行间隔(毫秒)
|
|
6
|
-
private isRunning: boolean = false; // 运行状态
|
|
7
|
-
private timeoutId?: number // 定时器 ID
|
|
8
|
-
private resolveCurrentWait?: () => void // 用于中断等待的 resolve 函数
|
|
9
|
-
|
|
10
|
-
constructor(task: PollerTask, interval: number) {
|
|
11
|
-
this.task = task
|
|
12
|
-
this.interval = interval
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// 异步执行循环
|
|
16
|
-
private async run(): Promise<void> {
|
|
17
|
-
while (this.isRunning) {
|
|
18
|
-
try {
|
|
19
|
-
await this.task() // 执行任务(同步/异步)
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error("Task execution error:", error) // 错误处理
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// 等待指定间隔(可被 stop 中断)
|
|
25
|
-
await new Promise<void>((resolve) => {
|
|
26
|
-
this.resolveCurrentWait = resolve
|
|
27
|
-
this.timeoutId = setTimeout(() => {
|
|
28
|
-
this.resolveCurrentWait = undefined
|
|
29
|
-
resolve()
|
|
30
|
-
}, this.interval)
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// 启动轮训
|
|
36
|
-
start(): void {
|
|
37
|
-
if (this.isRunning) return
|
|
38
|
-
this.isRunning = true
|
|
39
|
-
this.run()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 停止轮训
|
|
43
|
-
stop(): void {
|
|
44
|
-
if (!this.isRunning) return
|
|
45
|
-
this.isRunning = false
|
|
46
|
-
|
|
47
|
-
// 清除定时器和立即结束等待
|
|
48
|
-
if (this.timeoutId) {
|
|
49
|
-
clearTimeout(this.timeoutId)
|
|
50
|
-
this.timeoutId = undefined
|
|
51
|
-
}
|
|
52
|
-
if (this.resolveCurrentWait) {
|
|
53
|
-
this.resolveCurrentWait()
|
|
54
|
-
this.resolveCurrentWait = undefined
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { catchE, catchP } from '.'
|
|
3
|
-
|
|
4
|
-
describe('@helper/catch test', () => {
|
|
5
|
-
it('test catchP', async () => {
|
|
6
|
-
const testCases = [
|
|
7
|
-
{ input: Promise.reject(1), output: [undefined, 1] },
|
|
8
|
-
{ input: Promise.resolve(1), output: [1, undefined] },
|
|
9
|
-
{ input: Promise.reject({}), output: [undefined, {}] },
|
|
10
|
-
{ input: Promise.resolve({}), output: [{}, undefined] },
|
|
11
|
-
{ input: Promise.reject(null), output: [undefined, null] },
|
|
12
|
-
{ input: Promise.resolve(null), output: [null, undefined] },
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
for (let index = 0; index < testCases.length; index++) {
|
|
16
|
-
const testCase = testCases[index]
|
|
17
|
-
const result = await catchP(testCase.input)
|
|
18
|
-
expect(result).toEqual(testCase.output)
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('test catchE', async () => {
|
|
23
|
-
const testCases = [
|
|
24
|
-
{ input: () => { throw 1 }, output: [undefined, 1] },
|
|
25
|
-
{ input: () => { return 1 }, output: [1, undefined] },
|
|
26
|
-
{ input: () => { throw {} }, output: [undefined, {}] },
|
|
27
|
-
{ input: () => { return {} }, output: [{}, undefined] },
|
|
28
|
-
{ input: () => { throw null }, output: [undefined, null] },
|
|
29
|
-
{ input: () => { return null }, output: [null, undefined] },
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
for (let index = 0; index < testCases.length; index++) {
|
|
33
|
-
const testCase = testCases[index]
|
|
34
|
-
const result = await catchE(testCase.input)
|
|
35
|
-
expect(result).toEqual(testCase.output)
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* 将 Promise<R> 转换成 [resolve:R, reject:unknown] 的形式
|
|
4
|
-
*/
|
|
5
|
-
export async function catchP<R>(p: Promise<R>): Promise<[R, unknown]> {
|
|
6
|
-
const returned: [R, unknown] = [undefined, undefined] as unknown as [R, unknown]
|
|
7
|
-
|
|
8
|
-
await p
|
|
9
|
-
.then((result) => (returned[0] = result))
|
|
10
|
-
.catch((error: unknown) => (returned[1] = error))
|
|
11
|
-
|
|
12
|
-
return returned
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type CatchType<F extends () => unknown> = F extends () => Promise<infer R> ? R : F extends () => infer R ? R : never
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 执行函数 ()=>R 并以 [return: R, error:unknown] 的形式返回结果
|
|
19
|
-
*/
|
|
20
|
-
export async function catchE<F extends () => unknown>(f: F): Promise<[CatchType<F>, unknown]> {
|
|
21
|
-
const returned: [CatchType<F>, unknown] = [undefined, undefined] as unknown as [CatchType<F>, unknown]
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const result = f()
|
|
25
|
-
if (result instanceof Promise) {
|
|
26
|
-
return catchP(result)
|
|
27
|
-
} else {
|
|
28
|
-
returned[0] = result as CatchType<F>
|
|
29
|
-
}
|
|
30
|
-
} catch (error) {
|
|
31
|
-
returned[1] = error
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return returned
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
declare global {
|
|
38
|
-
interface Promise<T> {
|
|
39
|
-
result<R = T>(): Promise<[R, unknown]>
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
Promise.prototype.result = function () {
|
|
44
|
-
return catchP(this)
|
|
45
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|