@zk-tech/bedrock 0.0.1 → 0.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.
Files changed (221) hide show
  1. package/dist/async/index.cjs.map +1 -1
  2. package/dist/async/index.d.cts +2 -2
  3. package/dist/async/index.d.ts +2 -2
  4. package/dist/async/index.js.map +1 -1
  5. package/dist/error/index.cjs.map +1 -1
  6. package/dist/error/index.d.cts +19 -19
  7. package/dist/error/index.d.ts +19 -19
  8. package/dist/error/index.js.map +1 -1
  9. package/dist/{error-base-B4zaiJ5m.d.cts → error-base-DOFtBFla.d.cts} +8 -8
  10. package/dist/{error-base-B4zaiJ5m.d.ts → error-base-DOFtBFla.d.ts} +8 -8
  11. package/dist/promise/index.cjs.map +1 -1
  12. package/dist/promise/index.d.cts +4 -4
  13. package/dist/promise/index.d.ts +4 -4
  14. package/dist/promise/index.js.map +1 -1
  15. package/dist/worker/index.cjs.map +1 -1
  16. package/dist/worker/index.d.cts +2 -2
  17. package/dist/worker/index.d.ts +2 -2
  18. package/dist/worker/index.js.map +1 -1
  19. package/package.json +1 -2
  20. package/src/_internal/logger.ts +0 -59
  21. package/src/array/array.test.ts +0 -35
  22. package/src/array/array.ts +0 -25
  23. package/src/array/index.ts +0 -1
  24. package/src/assert/assert.test.ts +0 -86
  25. package/src/assert/assert.ts +0 -42
  26. package/src/assert/index.ts +0 -2
  27. package/src/async/barrier.test.ts +0 -90
  28. package/src/async/barrier.ts +0 -58
  29. package/src/async/cancellation.test.ts +0 -85
  30. package/src/async/cancellation.ts +0 -193
  31. package/src/async/index.ts +0 -18
  32. package/src/async/queue/queue.test.ts +0 -70
  33. package/src/async/queue/queue.ts +0 -56
  34. package/src/async/queue/task.test.ts +0 -155
  35. package/src/async/queue/task.ts +0 -67
  36. package/src/async/utils.test.ts +0 -28
  37. package/src/async/utils.ts +0 -8
  38. package/src/async/wait.ts +0 -9
  39. package/src/byte/format.test.ts +0 -64
  40. package/src/byte/format.ts +0 -44
  41. package/src/byte/index.ts +0 -2
  42. package/src/byte/node_modules/.vitest/results.json +0 -1
  43. package/src/byte/var.ts +0 -11
  44. package/src/cache/index.ts +0 -2
  45. package/src/cache/lru-with-timeout.test.ts +0 -88
  46. package/src/cache/lru-with-timeout.ts +0 -85
  47. package/src/cache/lru.test.ts +0 -56
  48. package/src/cache/lru.ts +0 -59
  49. package/src/context/context.test.ts +0 -17
  50. package/src/context/context.ts +0 -60
  51. package/src/context/index.ts +0 -8
  52. package/src/di/base.ts +0 -73
  53. package/src/di/container-service.test.ts +0 -179
  54. package/src/di/context.web.tsx +0 -41
  55. package/src/di/descriptor.ts +0 -31
  56. package/src/di/idle-value.test.ts +0 -73
  57. package/src/di/idle-value.ts +0 -63
  58. package/src/di/index.common.ts +0 -32
  59. package/src/di/index.ts +0 -2
  60. package/src/di/instantiation-service.interface.ts +0 -46
  61. package/src/di/instantiation-service.test.ts +0 -337
  62. package/src/di/instantiation-service.ts +0 -468
  63. package/src/di/lazy/foo.mock.ts +0 -28
  64. package/src/di/lazy/idle-load.ts +0 -39
  65. package/src/di/lazy/index.ts +0 -4
  66. package/src/di/lazy/lazy-service.test.ts +0 -65
  67. package/src/di/lazy/lazy-service.ts +0 -71
  68. package/src/di/lazy/type.ts +0 -5
  69. package/src/di/node_modules/.vitest/results.json +0 -1
  70. package/src/di/proxy-builder.test.ts +0 -45
  71. package/src/di/proxy-builder.ts +0 -38
  72. package/src/di/service-collection.test.ts +0 -27
  73. package/src/di/service-collection.ts +0 -46
  74. package/src/di/service-ownership-collection.test.ts +0 -39
  75. package/src/di/service-ownership-collection.ts +0 -38
  76. package/src/di/service-registry.test.ts +0 -66
  77. package/src/di/service-registry.ts +0 -99
  78. package/src/di/trace.ts +0 -85
  79. package/src/dispose/disposable-store.test.ts +0 -57
  80. package/src/dispose/disposable-store.ts +0 -80
  81. package/src/dispose/disposable-t.test.ts +0 -123
  82. package/src/dispose/disposable-t.ts +0 -238
  83. package/src/dispose/disposable-utils.test.ts +0 -15
  84. package/src/dispose/disposable-utils.ts +0 -28
  85. package/src/dispose/dispose-base.ts +0 -9
  86. package/src/dispose/index.ts +0 -34
  87. package/src/dispose/logger.test.ts +0 -65
  88. package/src/dispose/logger.ts +0 -39
  89. package/src/dispose/timer.test.ts +0 -30
  90. package/src/dispose/timer.ts +0 -16
  91. package/src/dispose/tracker.test.ts +0 -51
  92. package/src/dispose/tracker.ts +0 -105
  93. package/src/error/error-base.ts +0 -45
  94. package/src/error/error-code.ts +0 -39
  95. package/src/error/error-const.test.ts +0 -30
  96. package/src/error/error-const.ts +0 -16
  97. package/src/error/error-or.test.ts +0 -44
  98. package/src/error/error-or.ts +0 -2
  99. package/src/error/error-t.test.ts +0 -116
  100. package/src/error/error-t.ts +0 -100
  101. package/src/error/index.ts +0 -24
  102. package/src/error/node_modules/.vitest/results.json +0 -1
  103. package/src/event/disposable-linked-list.ts +0 -29
  104. package/src/event/emitter.test.ts +0 -191
  105. package/src/event/emitter.ts +0 -162
  106. package/src/event/error-handler.ts +0 -22
  107. package/src/event/index.ts +0 -34
  108. package/src/event/once.ts +0 -29
  109. package/src/event/phase-emitter.test.ts +0 -212
  110. package/src/event/phase-emitter.ts +0 -209
  111. package/src/event/shortcut-event-utils.ts +0 -33
  112. package/src/event/utils.ts +0 -6
  113. package/src/event/when.ts +0 -40
  114. package/src/function/debounce.test.ts +0 -274
  115. package/src/function/debounce.ts +0 -168
  116. package/src/function/index.ts +0 -2
  117. package/src/function/node_modules/.vitest/results.json +0 -1
  118. package/src/function/throttle.test.ts +0 -179
  119. package/src/function/throttle.ts +0 -26
  120. package/src/hash/hash-t.test.ts +0 -100
  121. package/src/hash/hash-t.ts +0 -51
  122. package/src/hash/index.ts +0 -3
  123. package/src/json/index.ts +0 -1
  124. package/src/json/node_modules/.vitest/results.json +0 -1
  125. package/src/json/parse.ts +0 -19
  126. package/src/launch/abstract-job.ts +0 -45
  127. package/src/launch/cost-recorder.ts +0 -22
  128. package/src/launch/index.ts +0 -2
  129. package/src/launch/job-scheduler.test.ts +0 -122
  130. package/src/launch/job-scheduler.ts +0 -118
  131. package/src/launch/node_modules/.vitest/deps/_metadata.json +0 -8
  132. package/src/launch/node_modules/.vitest/deps/package.json +0 -3
  133. package/src/launch/node_modules/.vitest/results.json +0 -1
  134. package/src/lock/README.md +0 -11
  135. package/src/lock/capability.test.ts +0 -110
  136. package/src/lock/capability.ts +0 -89
  137. package/src/lock/index.ts +0 -15
  138. package/src/lock/node_modules/.vitest/results.json +0 -1
  139. package/src/lock/semaphore.ts +0 -21
  140. package/src/lock/shared-mutex.test.ts +0 -537
  141. package/src/lock/shared-mutex.ts +0 -242
  142. package/src/lock/utils.test.ts +0 -165
  143. package/src/lock/utils.ts +0 -135
  144. package/src/lodash-es/index.ts +0 -1
  145. package/src/math/degree.ts +0 -16
  146. package/src/math/index.ts +0 -7
  147. package/src/math/math.test.ts +0 -40
  148. package/src/math/math.ts +0 -64
  149. package/src/math/node_modules/.vitest/results.json +0 -1
  150. package/src/math/vector.test.ts +0 -73
  151. package/src/math/vector.ts +0 -114
  152. package/src/network/client.interface.ts +0 -104
  153. package/src/network/client.web.ts +0 -24
  154. package/src/network/index.common.ts +0 -10
  155. package/src/network/index.ts +0 -2
  156. package/src/network/plugins/retry.ts +0 -98
  157. package/src/objects/deep-clone.test.ts +0 -40
  158. package/src/objects/deep-clone.ts +0 -13
  159. package/src/objects/deep-equal.test.ts +0 -86
  160. package/src/objects/deep-equal.ts +0 -60
  161. package/src/objects/index.ts +0 -4
  162. package/src/platform/index.ts +0 -64
  163. package/src/promise/index.ts +0 -16
  164. package/src/promise/promise.test.ts +0 -254
  165. package/src/promise/promise.ts +0 -212
  166. package/src/scheduler/callback-token.ts +0 -31
  167. package/src/scheduler/core/actuator-args.test.ts +0 -47
  168. package/src/scheduler/core/actuator.test.ts +0 -82
  169. package/src/scheduler/core/actuator.ts +0 -58
  170. package/src/scheduler/core/chunk-scheduler.test.ts +0 -54
  171. package/src/scheduler/core/chunk-scheduler.ts +0 -28
  172. package/src/scheduler/core/node_modules/.vitest/results.json +0 -1
  173. package/src/scheduler/core/scheduler.test.ts +0 -328
  174. package/src/scheduler/core/scheduler.ts +0 -172
  175. package/src/scheduler/core/task-queue.test.ts +0 -78
  176. package/src/scheduler/core/task-queue.ts +0 -44
  177. package/src/scheduler/core/task.test.ts +0 -34
  178. package/src/scheduler/core/task.ts +0 -52
  179. package/src/scheduler/core/utils.ts +0 -48
  180. package/src/scheduler/executor/abstract-executor.test.ts +0 -44
  181. package/src/scheduler/executor/abstract-executor.ts +0 -38
  182. package/src/scheduler/executor/executor.interface.ts +0 -39
  183. package/src/scheduler/executor/idle-callback-executor.test.ts +0 -70
  184. package/src/scheduler/executor/idle-callback-executor.ts +0 -98
  185. package/src/scheduler/executor/make-executor.ts +0 -18
  186. package/src/scheduler/executor/post-message-executor.test.ts +0 -66
  187. package/src/scheduler/executor/post-message-executor.ts +0 -52
  188. package/src/scheduler/index.ts +0 -15
  189. package/src/scheduler/lv-scheduler-callback.ts +0 -19
  190. package/src/scheduler/lv-scheduler-config.ts +0 -17
  191. package/src/scheduler/type.ts +0 -48
  192. package/src/sprintf/index.ts +0 -2
  193. package/src/sprintf/sprintf.test.ts +0 -95
  194. package/src/sprintf/sprintf.ts +0 -97
  195. package/src/structure/graph.test.ts +0 -181
  196. package/src/structure/graph.ts +0 -105
  197. package/src/structure/index.ts +0 -8
  198. package/src/structure/linked-list.test.ts +0 -74
  199. package/src/structure/linked-list.ts +0 -145
  200. package/src/structure/min-heap.test.ts +0 -71
  201. package/src/structure/min-heap.ts +0 -91
  202. package/src/type/REAME.md +0 -2
  203. package/src/type/distributive-omit.interface.ts +0 -4
  204. package/src/type/index.ts +0 -3
  205. package/src/type/object-key-paths.interface.ts +0 -40
  206. package/src/undo-redo-stack/README.md +0 -61
  207. package/src/undo-redo-stack/action-stack.test.ts +0 -330
  208. package/src/undo-redo-stack/action-stack.ts +0 -150
  209. package/src/undo-redo-stack/element.ts +0 -4
  210. package/src/undo-redo-stack/index.ts +0 -7
  211. package/src/undo-redo-stack/state-stack.test.ts +0 -118
  212. package/src/undo-redo-stack/state-stack.ts +0 -133
  213. package/src/uuid/index.ts +0 -7
  214. package/src/uuid/uuid.ts +0 -86
  215. package/src/worker/cors-worker.ts +0 -38
  216. package/src/worker/index.ts +0 -4
  217. package/src/worker/node_modules/.vitest/results.json +0 -1
  218. package/src/worker/promise-worker-main-thread.test.ts +0 -91
  219. package/src/worker/promise-worker-main-thread.ts +0 -76
  220. package/src/worker/promise-worker-worker-thread.ts +0 -64
  221. package/src/worker/promise-worker.interface.ts +0 -15
@@ -1,209 +0,0 @@
1
- import { lvAssert } from '@/assert';
2
- import { Emitter, type Event, type EmitterOptions } from './emitter';
3
- import {
4
- type IMakeShortcutEvent,
5
- makeSyncShortcutEvent,
6
- makeAsyncShortcutEvent,
7
- } from './shortcut-event-utils';
8
- import type { IDisposable } from '@/dispose';
9
- import { Logger } from '@/_internal/logger';
10
-
11
- export interface IPhaseChecker<T> {
12
- (before: T, after: T): boolean;
13
- }
14
-
15
- function defaultCheck<T>(_before: T, _after: T) {
16
- return true;
17
- }
18
-
19
- /**
20
- * WhenPhaseEvent相比较Event有如下特点
21
- * 1. 增加了callback前第一个参数,可以明确listener对应的phase
22
- * 2. 会进行状态补发
23
- */
24
- export interface WhenPhaseEvent<T> {
25
- (phase: T, listener: () => any): IDisposable;
26
- }
27
-
28
- /**
29
- * PhaseEvent相比较Event有如下特点
30
- * 1. 参数一定为空
31
- * 2. 会进行状态补发
32
- */
33
- export type PhaseEvent = Event<[]>;
34
-
35
- interface IPhaseEmitter {
36
- emitter: Emitter<[]>;
37
- fn: Event<[]>;
38
- }
39
-
40
- export enum ShortcutEventMode {
41
- Async,
42
- Sync,
43
- }
44
-
45
- interface IPhaseEmitterConfig<T> {
46
- checker?: IPhaseChecker<T>;
47
- shortcutEventMode?: ShortcutEventMode;
48
- }
49
-
50
- /**
51
- * 阶段状态事件触发器,相比较原始的emitter有如下不同
52
- * 1. 明确了事件类型一定是生命周期的扭转
53
- * a. 必须传入一个枚举表示阶段状态
54
- * b. 抛出的事件只能是生命周期扭转,不允许携带参数
55
- *
56
- * 2. 当状态已经到达,后监听,进行补发事件
57
- *
58
- * -------------------------
59
- * 注意:由于存在事件补发,所以该事件触发器其实很危险,冲击到了依赖关系
60
- * 本身A依赖B的某个事件,那么正确的顺序应该是:
61
- * B模块初始化->A模块初始化->B抛出事件->A监听到事件
62
- *
63
- * 但如果存在事件补发,以下流程表面没有问题
64
- * B模块初始化->B抛出事件->A模块初始化->A监听到事件
65
- * 实际上可能有两个问题
66
- * 1. A监听到的事件,并不清楚在A初始化前触发还是初始化后触发,信息丢失
67
- * 2. B抛出事件,A其实必须要响应,响应晚了其实也是问题
68
- *
69
- * 所以事件补发是一件非常危险的事情,不要随意补发。
70
- * -------------------------
71
- *
72
- * 只有状态扭转的事件可以存在合理的补发
73
- * A监听B的状态变更
74
- * 一般来说,A模块内代码的写法可能是
75
- * ```
76
- * if (B.isReady) {
77
- * doSomething();
78
- * } else {
79
- * B.onReady(doSomething);
80
- * }
81
- * ```
82
- * 这种情况,我们借助事件补发可以变成如下来减少代码量。
83
- * ```
84
- * B.onReady(doSomething);
85
- * ```
86
- *
87
- * 最经典的事件补发就是CancellationSourceToken的设计,我们将其抽象出一种通用能力。
88
- * 使用demo如下:
89
- * ```
90
- * enum Phase {
91
- * Waiting,
92
- * Eventually,
93
- * }
94
- *
95
- * class Foo {
96
- * phaseEmitter = new PhaseEmitter<Phase>(Phase.Waiting);
97
- * // 方式1,监听指定的状态到达
98
- * // 外部: foo.onEventually(doSomething);
99
- * onEventually = this.phaseEmitter.when(Phase.Eventually);
100
- *
101
- * // 方式2,给予外部更高的自由度
102
- * // 外部: foo.onPhase(Phase.Eventually, doSomething);
103
- * onPhase = this.phaseEmitter.whenPhase;
104
- *
105
- * // 方式3,监听变更(该方式不会补发)
106
- * // 外部: foo.onPhaseChange((phase) => doSomething)
107
- * onPhaseChange = this.phaseEmitter.event;
108
- * }
109
- * ```
110
- * 有问题联系基建侧同学。
111
- */
112
- export class PhaseEmitter<T, K extends T = T> {
113
- private _globalEmitter?: Emitter<[T]>;
114
- private readonly _phaseEmitterMap: Map<K, IPhaseEmitter> = new Map();
115
- private _phaseEvent?: WhenPhaseEvent<T>;
116
- private readonly _shortcutEvent: IMakeShortcutEvent<T>;
117
-
118
- constructor(
119
- private _currentPhase: K,
120
- config: IPhaseEmitterConfig<T> = {},
121
- private readonly _phaseChecker: IPhaseChecker<T> = defaultCheck,
122
- private readonly _options?: EmitterOptions,
123
- ) {
124
- this._phaseChecker = config.checker ?? defaultCheck;
125
-
126
- const shortcutEventMode = config.shortcutEventMode ?? ShortcutEventMode.Async;
127
- this._shortcutEvent =
128
- shortcutEventMode === ShortcutEventMode.Async ? makeAsyncShortcutEvent : makeSyncShortcutEvent;
129
- }
130
-
131
- get currentPhase() {
132
- return this._currentPhase;
133
- }
134
-
135
- get event(): Event<[T]> {
136
- if (!this._globalEmitter) {
137
- this._globalEmitter = new Emitter<T[]>();
138
- }
139
- return this._globalEmitter!.event;
140
- }
141
-
142
- get whenPhase(): WhenPhaseEvent<T> {
143
- if (this._phaseEvent) {
144
- return this._phaseEvent;
145
- }
146
-
147
- this._phaseEvent = (phase: T, listener: () => any) => {
148
- if (this._currentPhase === phase) {
149
- return this._shortcutEvent(this._currentPhase)(listener);
150
- }
151
- if (!this._phaseEmitterMap.has(phase as K)) {
152
- this._setPhaseEmitter(phase as K);
153
- }
154
- return this._phaseEmitterMap.get(phase as K)!.fn(listener);
155
- };
156
-
157
- return this._phaseEvent;
158
- }
159
-
160
- when(phase: K): PhaseEvent {
161
- if (this._currentPhase === phase) {
162
- return this._shortcutEvent(phase);
163
- }
164
-
165
- if (!this._phaseEmitterMap.has(phase)) {
166
- this._setPhaseEmitter(phase);
167
- }
168
- return this._phaseEmitterMap.get(phase)!.fn;
169
- }
170
-
171
- dispose(): void {
172
- for (const [_phase, emitter] of this._phaseEmitterMap) {
173
- emitter.emitter.dispose();
174
- }
175
- this._globalEmitter?.dispose();
176
- }
177
-
178
- setPhase(phase: K): void {
179
- if (this._currentPhase === phase) {
180
- Logger.warn(`duplicate set phase: ${phase}.`);
181
- return;
182
- }
183
- lvAssert(this._phaseChecker(this._currentPhase, phase));
184
- this._currentPhase = phase;
185
- this._phaseEmitterMap.get(phase)?.emitter.fire();
186
- this._globalEmitter?.fire(phase);
187
- }
188
-
189
- /**
190
- * 该接口为了和emitter对齐,优先使用setPhase
191
- * @deprecated 优先使用setPhase,未来可能会去掉
192
- */
193
- fire(phase: K): void {
194
- this.setPhase(phase);
195
- }
196
-
197
- private _setPhaseEmitter(phase: K) {
198
- const emitter = new Emitter<[]>(this._options);
199
- this._phaseEmitterMap.set(phase, {
200
- emitter,
201
- fn: (listener: () => any) => {
202
- if (this._currentPhase === phase) {
203
- return this._shortcutEvent(this._currentPhase)(listener);
204
- }
205
- return emitter.event(listener);
206
- },
207
- });
208
- }
209
- }
@@ -1,33 +0,0 @@
1
- import type { IDisposable } from '@/dispose';
2
- import type { Event } from './emitter';
3
-
4
- export interface IMakeShortcutEvent<T> {
5
- (val: T): Event<[T]>;
6
- }
7
-
8
- export function makeSyncShortcutEvent<T>(val: T) {
9
- return function (callback: (val: T) => void): IDisposable {
10
- callback(val);
11
-
12
- return {
13
- dispose() {
14
- // eslint-disable-next-line @typescript-eslint/no-empty-function
15
- },
16
- };
17
- };
18
- }
19
-
20
- export function makeAsyncShortcutEvent<T>(val: T) {
21
- return function (callback: (val: T) => void): IDisposable {
22
- const handle = setTimeout(() => {
23
- callback(val);
24
- }, 0);
25
-
26
- return {
27
- dispose() {
28
- clearTimeout(handle);
29
- },
30
- };
31
- };
32
- }
33
-
@@ -1,6 +0,0 @@
1
- import { EmptyDispose } from '@/dispose';
2
- import type { Event } from './emitter';
3
-
4
- export const NeverEvent: Event<[any]> = () => {
5
- return EmptyDispose;
6
- };
package/src/event/when.ts DELETED
@@ -1,40 +0,0 @@
1
- import type { Event } from './emitter';
2
- import type { IDisposable } from '@/dispose';
3
-
4
- // 辅助能力:监听事件,直到事件满足某种状况为止,此时触发 listener callback 并停止监听
5
- // 类似 MobX 的 `when`
6
- export function listenWhen<TArgs extends any[]>(
7
- event: Event<TArgs>,
8
- predicate: (...args: TArgs) => boolean,
9
- ): Event<TArgs> {
10
- return (listener, thisArgs = null) => {
11
- let hasBeenFulfilled = false;
12
-
13
- // 必须这样写,事件可能同步触发
14
- // eslint-disable-next-line no-undef-init
15
- let result: IDisposable | undefined = undefined;
16
-
17
- result = event((...args) => {
18
- if (hasBeenFulfilled) {
19
- result?.dispose();
20
- return;
21
- }
22
-
23
- // 是否条件满足
24
- hasBeenFulfilled = predicate(...args);
25
-
26
- // 如果满足条件则触发回调
27
- if (hasBeenFulfilled) {
28
- listener.call(thisArgs, ...args);
29
- result?.dispose();
30
- }
31
- }, null);
32
-
33
- // 注册事件时可能就会被触发一次?
34
- if (hasBeenFulfilled) {
35
- result.dispose();
36
- }
37
-
38
- return result;
39
- };
40
- }
@@ -1,274 +0,0 @@
1
- /* eslint-disable max-lines-per-function */
2
- import { sleep } from '../async';
3
- import { debounce } from './debounce';
4
-
5
- describe('Debounce', () => {
6
- test('should debounce a function', async () => {
7
- let callCount = 0;
8
-
9
- const debounced = debounce(function (value) {
10
- ++callCount;
11
- return value;
12
- }, 32);
13
-
14
- const results = [debounced('a'), debounced('b'), debounced('c')];
15
- expect(results).toEqual([undefined, undefined, undefined]);
16
- expect(callCount).toBe(0);
17
-
18
- setTimeout(() => {
19
- expect(callCount).toBe(1);
20
-
21
- const results = [debounced('d'), debounced('e'), debounced('f')];
22
- expect(results).toEqual(['c', 'c', 'c']);
23
- expect(callCount).toBe(1);
24
- }, 128);
25
-
26
- await sleep(256);
27
- expect(callCount).toBe(2);
28
- });
29
-
30
- test('subsequent debounced calls return the last func result', async () => {
31
- const identity = (x: string) => x;
32
- const debounced = debounce(identity, 32);
33
- debounced('a');
34
-
35
- setTimeout(() => {
36
- expect(debounced('b')).not.toBe('b');
37
- }, 64);
38
-
39
- await sleep(128);
40
- expect(debounced('c')).not.toBe('c');
41
- });
42
-
43
- test('should not immediately call func when wait is 0', async () => {
44
- let callCount = 0;
45
- const debounced = debounce(() => {
46
- ++callCount;
47
- }, 0);
48
-
49
- debounced();
50
- debounced();
51
- expect(callCount).toBe(0);
52
-
53
- await sleep(5);
54
- expect(callCount).toBe(1);
55
- });
56
-
57
- test('should apply default options', async () => {
58
- let callCount = 0;
59
- const debounced = debounce(
60
- () => {
61
- callCount++;
62
- },
63
- 32,
64
- {},
65
- );
66
-
67
- debounced();
68
- expect(callCount).toBe(0);
69
-
70
- await sleep(64);
71
- expect(callCount).toBe(1);
72
- });
73
-
74
- test('should support a leading option', async () => {
75
- const callCounts = [0, 0];
76
-
77
- const withLeading = debounce(
78
- () => {
79
- callCounts[0]++;
80
- },
81
- 32,
82
- { leading: true },
83
- );
84
-
85
- const withLeadingAndTrailing = debounce(
86
- () => {
87
- callCounts[1]++;
88
- },
89
- 32,
90
- { leading: true, trailing: true },
91
- );
92
-
93
- withLeading();
94
- expect(callCounts[0]).toBe(1);
95
-
96
- withLeadingAndTrailing();
97
- withLeadingAndTrailing();
98
- expect(callCounts[1]).toBe(1);
99
-
100
- await sleep(64);
101
- expect(callCounts).toEqual([1, 2]);
102
-
103
- withLeading();
104
- expect(callCounts[0]).toBe(2);
105
- });
106
-
107
- test('subsequent leading debounced calls return the last func result', async () => {
108
- const debounced = debounce((x: string) => x, 32, { leading: true, trailing: false });
109
- const results = [debounced('a'), debounced('b')];
110
-
111
- expect(results).toEqual(['a', 'a']);
112
-
113
- await sleep(64);
114
- const results2 = [debounced('c'), debounced('d')];
115
- expect(results2).toEqual(['c', 'c']);
116
- });
117
-
118
- test('should support a trailing option', async () => {
119
- let withCount = 0;
120
- let withoutCount = 0;
121
-
122
- const withTrailing = debounce(
123
- () => {
124
- withCount++;
125
- },
126
- 32,
127
- { trailing: true },
128
- );
129
-
130
- const withoutTrailing = debounce(
131
- () => {
132
- withoutCount++;
133
- },
134
- 32,
135
- { trailing: false },
136
- );
137
-
138
- withTrailing();
139
- expect(withCount).toBe(0);
140
-
141
- withoutTrailing();
142
- expect(withoutCount).toBe(0);
143
-
144
- await sleep(64);
145
- expect(withCount).toBe(1);
146
- expect(withoutCount).toBe(0);
147
- });
148
-
149
- test('should support a maxWait option', async () => {
150
- let callCount = 0;
151
-
152
- const debounced = debounce(
153
- () => {
154
- callCount++;
155
- },
156
- 32,
157
- { maxWait: 64 },
158
- );
159
-
160
- debounced();
161
- debounced();
162
- expect(callCount).toBe(0);
163
-
164
- // 超过原来的 maxWait 时间,不足下一个
165
- await sleep(128);
166
- expect(callCount).toBe(1); // maxWait 时间后应该调用过一次
167
- debounced();
168
- debounced();
169
- expect(callCount).toBe(1); // 紧接着调用不会立即触发因为还在 maxWait 窗口内
170
-
171
- // 确保超过第二个 maxWait 时间
172
- await sleep(128);
173
- expect(callCount).toBe(2); // 经过足够时间后,第二次 maxWait 达成,调用发生
174
- });
175
-
176
- test('should support maxWait in a tight loop', async () => {
177
- const limit = 320;
178
- let withCount = 0;
179
- let withoutCount = 0;
180
-
181
- const withMaxWait = debounce(
182
- () => {
183
- withCount++;
184
- },
185
- 64,
186
- { maxWait: 128 },
187
- );
188
-
189
- const withoutMaxWait = debounce(() => {
190
- withoutCount++;
191
- }, 96);
192
-
193
- const start = Date.now();
194
- while (Date.now() - start < limit) {
195
- withMaxWait();
196
- withoutMaxWait();
197
- }
198
-
199
- const actual = [Boolean(withoutCount), Boolean(withCount)];
200
- await sleep(1);
201
- expect(actual).toEqual([false, true]);
202
- });
203
-
204
- test('should queue a trailing call for subsequent debounced calls after maxWait', async () => {
205
- let callCount = 0;
206
-
207
- const debounced = debounce(
208
- () => {
209
- callCount++;
210
- },
211
- 200,
212
- { maxWait: 200 },
213
- );
214
-
215
- debounced(); // 第一次立即调用
216
-
217
- setTimeout(debounced, 190); // 在 maxWait 之前调用
218
- setTimeout(debounced, 200); // 正在 maxWait 边缘调用
219
- setTimeout(debounced, 210); // 刚过 maxWait 时调用
220
-
221
- // 等待足够时间以确保所有的debounce逻辑完成
222
- await sleep(500);
223
- expect(callCount).toBe(2); // 预期在 200 ms 后的某个时点触发了第二次调用
224
- });
225
-
226
- test('should cancel maxDelayed when delayed is invoked', async () => {
227
- let callCount = 0;
228
-
229
- const debounced = debounce(
230
- () => {
231
- callCount++;
232
- },
233
- 32,
234
- { maxWait: 64 },
235
- );
236
-
237
- debounced(); // 第一次立即调用
238
-
239
- setTimeout(() => {
240
- debounced(); // 第二次调用应该重置 maxWait 计时器
241
- expect(callCount).toBe(1); // 检查到目前为止该函数被调用的次数
242
- }, 128);
243
-
244
- // 等待足够时间以确保所有的debounce逻辑完成
245
- await sleep(256);
246
- expect(callCount).toBe(2); // 最后,确认函数被调用了两次
247
- });
248
-
249
- test('should invoke the trailing call with the correct arguments and this binding', async () => {
250
- let actual: any;
251
- let callCount = 0;
252
- const object = {};
253
-
254
- const debounced = debounce(
255
- function (value) {
256
- actual = [this];
257
- actual.push(value);
258
- return ++callCount !== 2;
259
- },
260
- 32,
261
- { leading: true, maxWait: 64 },
262
- );
263
-
264
- while (true) {
265
- if (!debounced.call(object, 'a')) {
266
- break;
267
- }
268
- }
269
-
270
- await sleep(64);
271
- expect(callCount).toBe(2);
272
- expect(actual).toEqual([object, 'a']);
273
- });
274
- });