@tanstack/pacer 0.8.0 → 0.9.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/dist/cjs/async-batcher.cjs +163 -0
- package/dist/cjs/async-batcher.cjs.map +1 -0
- package/dist/cjs/async-batcher.d.cts +273 -0
- package/dist/cjs/async-debouncer.cjs +149 -162
- package/dist/cjs/async-debouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer.d.cts +76 -57
- package/dist/cjs/async-queuer.cjs +282 -343
- package/dist/cjs/async-queuer.cjs.map +1 -1
- package/dist/cjs/async-queuer.d.cts +121 -100
- package/dist/cjs/async-rate-limiter.cjs +128 -185
- package/dist/cjs/async-rate-limiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter.d.cts +72 -61
- package/dist/cjs/async-throttler.cjs +168 -178
- package/dist/cjs/async-throttler.cjs.map +1 -1
- package/dist/cjs/async-throttler.d.cts +97 -69
- package/dist/cjs/batcher.cjs +110 -119
- package/dist/cjs/batcher.cjs.map +1 -1
- package/dist/cjs/batcher.d.cts +76 -51
- package/dist/cjs/debouncer.cjs +97 -85
- package/dist/cjs/debouncer.cjs.map +1 -1
- package/dist/cjs/debouncer.d.cts +54 -26
- package/dist/cjs/index.cjs +3 -6
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/queuer.cjs +246 -294
- package/dist/cjs/queuer.cjs.map +1 -1
- package/dist/cjs/queuer.d.cts +102 -81
- package/dist/cjs/rate-limiter.cjs +97 -130
- package/dist/cjs/rate-limiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter.d.cts +50 -37
- package/dist/cjs/throttler.cjs +107 -123
- package/dist/cjs/throttler.cjs.map +1 -1
- package/dist/cjs/throttler.d.cts +59 -35
- package/dist/cjs/utils.cjs +0 -13
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +0 -1
- package/dist/esm/async-batcher.d.ts +273 -0
- package/dist/esm/async-batcher.js +163 -0
- package/dist/esm/async-batcher.js.map +1 -0
- package/dist/esm/async-debouncer.d.ts +76 -57
- package/dist/esm/async-debouncer.js +149 -162
- package/dist/esm/async-debouncer.js.map +1 -1
- package/dist/esm/async-queuer.d.ts +121 -100
- package/dist/esm/async-queuer.js +282 -343
- package/dist/esm/async-queuer.js.map +1 -1
- package/dist/esm/async-rate-limiter.d.ts +72 -61
- package/dist/esm/async-rate-limiter.js +128 -185
- package/dist/esm/async-rate-limiter.js.map +1 -1
- package/dist/esm/async-throttler.d.ts +97 -69
- package/dist/esm/async-throttler.js +168 -178
- package/dist/esm/async-throttler.js.map +1 -1
- package/dist/esm/batcher.d.ts +76 -51
- package/dist/esm/batcher.js +110 -119
- package/dist/esm/batcher.js.map +1 -1
- package/dist/esm/debouncer.d.ts +54 -26
- package/dist/esm/debouncer.js +97 -85
- package/dist/esm/debouncer.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +4 -7
- package/dist/esm/queuer.d.ts +102 -81
- package/dist/esm/queuer.js +246 -294
- package/dist/esm/queuer.js.map +1 -1
- package/dist/esm/rate-limiter.d.ts +50 -37
- package/dist/esm/rate-limiter.js +97 -130
- package/dist/esm/rate-limiter.js.map +1 -1
- package/dist/esm/throttler.d.ts +59 -35
- package/dist/esm/throttler.js +107 -123
- package/dist/esm/throttler.js.map +1 -1
- package/dist/esm/utils.d.ts +0 -1
- package/dist/esm/utils.js +0 -13
- package/dist/esm/utils.js.map +1 -1
- package/package.json +14 -11
- package/src/async-batcher.ts +475 -0
- package/src/async-debouncer.ts +201 -121
- package/src/async-queuer.ts +337 -216
- package/src/async-rate-limiter.ts +176 -136
- package/src/async-throttler.ts +233 -139
- package/src/batcher.ts +158 -92
- package/src/debouncer.ts +135 -52
- package/src/index.ts +1 -1
- package/src/queuer.ts +348 -226
- package/src/rate-limiter.ts +125 -80
- package/src/throttler.ts +152 -78
- package/src/utils.ts +0 -15
- package/dist/cjs/compare.cjs +0 -72
- package/dist/cjs/compare.cjs.map +0 -1
- package/dist/cjs/compare.d.cts +0 -12
- package/dist/esm/compare.d.ts +0 -12
- package/dist/esm/compare.js +0 -72
- package/dist/esm/compare.js.map +0 -1
- package/src/compare.ts +0 -105
package/src/async-debouncer.ts
CHANGED
|
@@ -1,6 +1,62 @@
|
|
|
1
|
+
import { Store } from '@tanstack/store'
|
|
1
2
|
import { parseFunctionOrValue } from './utils'
|
|
2
3
|
import type { AnyAsyncFunction, OptionalKeys } from './types'
|
|
3
4
|
|
|
5
|
+
export interface AsyncDebouncerState<TFn extends AnyAsyncFunction> {
|
|
6
|
+
/**
|
|
7
|
+
* Whether the debouncer can execute on the leading edge of the timeout
|
|
8
|
+
*/
|
|
9
|
+
canLeadingExecute: boolean
|
|
10
|
+
/**
|
|
11
|
+
* Number of function executions that have resulted in errors
|
|
12
|
+
*/
|
|
13
|
+
errorCount: number
|
|
14
|
+
/**
|
|
15
|
+
* Whether the debounced function is currently executing asynchronously
|
|
16
|
+
*/
|
|
17
|
+
isExecuting: boolean
|
|
18
|
+
/**
|
|
19
|
+
* Whether the debouncer is waiting for the timeout to trigger execution
|
|
20
|
+
*/
|
|
21
|
+
isPending: boolean
|
|
22
|
+
/**
|
|
23
|
+
* The arguments from the most recent call to maybeExecute
|
|
24
|
+
*/
|
|
25
|
+
lastArgs: Parameters<TFn> | undefined
|
|
26
|
+
/**
|
|
27
|
+
* The result from the most recent successful function execution
|
|
28
|
+
*/
|
|
29
|
+
lastResult: ReturnType<TFn> | undefined
|
|
30
|
+
/**
|
|
31
|
+
* Number of function executions that have completed (either successfully or with errors)
|
|
32
|
+
*/
|
|
33
|
+
settleCount: number
|
|
34
|
+
/**
|
|
35
|
+
* Current execution status - 'idle' when not active, 'pending' when waiting, 'executing' when running, 'settled' when completed
|
|
36
|
+
*/
|
|
37
|
+
status: 'disabled' | 'idle' | 'pending' | 'executing' | 'settled'
|
|
38
|
+
/**
|
|
39
|
+
* Number of function executions that have completed successfully
|
|
40
|
+
*/
|
|
41
|
+
successCount: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getDefaultAsyncDebouncerState<
|
|
45
|
+
TFn extends AnyAsyncFunction,
|
|
46
|
+
>(): AsyncDebouncerState<TFn> {
|
|
47
|
+
return structuredClone({
|
|
48
|
+
canLeadingExecute: true,
|
|
49
|
+
errorCount: 0,
|
|
50
|
+
isExecuting: false,
|
|
51
|
+
isPending: false,
|
|
52
|
+
lastArgs: undefined,
|
|
53
|
+
lastResult: undefined,
|
|
54
|
+
settleCount: 0,
|
|
55
|
+
successCount: 0,
|
|
56
|
+
status: 'idle',
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
4
60
|
/**
|
|
5
61
|
* Options for configuring an async debounced function
|
|
6
62
|
*/
|
|
@@ -11,6 +67,10 @@ export interface AsyncDebouncerOptions<TFn extends AnyAsyncFunction> {
|
|
|
11
67
|
* Defaults to true.
|
|
12
68
|
*/
|
|
13
69
|
enabled?: boolean | ((debouncer: AsyncDebouncer<TFn>) => boolean)
|
|
70
|
+
/**
|
|
71
|
+
* Initial state for the async debouncer
|
|
72
|
+
*/
|
|
73
|
+
initialState?: Partial<AsyncDebouncerState<TFn>>
|
|
14
74
|
/**
|
|
15
75
|
* Whether to execute on the leading edge of the timeout.
|
|
16
76
|
* Defaults to false.
|
|
@@ -51,7 +111,7 @@ export interface AsyncDebouncerOptions<TFn extends AnyAsyncFunction> {
|
|
|
51
111
|
|
|
52
112
|
type AsyncDebouncerOptionsWithOptionalCallbacks = OptionalKeys<
|
|
53
113
|
AsyncDebouncerOptions<any>,
|
|
54
|
-
'onError' | 'onSettled' | 'onSuccess'
|
|
114
|
+
'initialState' | 'onError' | 'onSettled' | 'onSuccess'
|
|
55
115
|
>
|
|
56
116
|
|
|
57
117
|
const defaultOptions: AsyncDebouncerOptionsWithOptionalCallbacks = {
|
|
@@ -76,10 +136,18 @@ const defaultOptions: AsyncDebouncerOptionsWithOptionalCallbacks = {
|
|
|
76
136
|
* instead of setting the result on a state variable from within the debounced function.
|
|
77
137
|
*
|
|
78
138
|
* Error Handling:
|
|
79
|
-
* - If an
|
|
80
|
-
* - If
|
|
81
|
-
* -
|
|
82
|
-
* -
|
|
139
|
+
* - If an `onError` handler is provided, it will be called with the error and debouncer instance
|
|
140
|
+
* - If `throwOnError` is true (default when no onError handler is provided), the error will be thrown
|
|
141
|
+
* - If `throwOnError` is false (default when onError handler is provided), the error will be swallowed
|
|
142
|
+
* - Both onError and throwOnError can be used together - the handler will be called before any error is thrown
|
|
143
|
+
* - The error state can be checked using the underlying store
|
|
144
|
+
*
|
|
145
|
+
* State Management:
|
|
146
|
+
* - The debouncer uses a reactive store for state management
|
|
147
|
+
* - Use `initialState` to provide initial state values when creating the async debouncer
|
|
148
|
+
* - The state includes canLeadingExecute, error count, execution status, and success/settle counts
|
|
149
|
+
* - State can be accessed via the `store` property and its `state` getter
|
|
150
|
+
* - The store is reactive and will notify subscribers of state changes
|
|
83
151
|
*
|
|
84
152
|
* @example
|
|
85
153
|
* ```ts
|
|
@@ -99,18 +167,13 @@ const defaultOptions: AsyncDebouncerOptionsWithOptionalCallbacks = {
|
|
|
99
167
|
* ```
|
|
100
168
|
*/
|
|
101
169
|
export class AsyncDebouncer<TFn extends AnyAsyncFunction> {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
private _lastResult: ReturnType<TFn> | undefined
|
|
110
|
-
private _settleCount = 0
|
|
111
|
-
private _successCount = 0
|
|
112
|
-
private _timeoutId: NodeJS.Timeout | null = null
|
|
113
|
-
private _resolvePreviousPromise:
|
|
170
|
+
readonly store: Store<Readonly<AsyncDebouncerState<TFn>>> = new Store<
|
|
171
|
+
AsyncDebouncerState<TFn>
|
|
172
|
+
>(getDefaultAsyncDebouncerState<TFn>())
|
|
173
|
+
options: AsyncDebouncerOptions<TFn>
|
|
174
|
+
#abortController: AbortController | null = null
|
|
175
|
+
#timeoutId: NodeJS.Timeout | null = null
|
|
176
|
+
#resolvePreviousPromise:
|
|
114
177
|
| ((value?: ReturnType<TFn> | undefined) => void)
|
|
115
178
|
| null = null
|
|
116
179
|
|
|
@@ -118,44 +181,60 @@ export class AsyncDebouncer<TFn extends AnyAsyncFunction> {
|
|
|
118
181
|
private fn: TFn,
|
|
119
182
|
initialOptions: AsyncDebouncerOptions<TFn>,
|
|
120
183
|
) {
|
|
121
|
-
this.
|
|
184
|
+
this.options = {
|
|
122
185
|
...defaultOptions,
|
|
123
186
|
...initialOptions,
|
|
124
187
|
throwOnError: initialOptions.throwOnError ?? !initialOptions.onError,
|
|
125
188
|
}
|
|
189
|
+
this.#setState(this.options.initialState ?? {})
|
|
126
190
|
}
|
|
127
191
|
|
|
128
192
|
/**
|
|
129
|
-
* Updates the debouncer options
|
|
193
|
+
* Updates the async debouncer options
|
|
130
194
|
*/
|
|
131
|
-
setOptions(newOptions: Partial<AsyncDebouncerOptions<TFn>>): void {
|
|
132
|
-
this.
|
|
195
|
+
setOptions = (newOptions: Partial<AsyncDebouncerOptions<TFn>>): void => {
|
|
196
|
+
this.options = { ...this.options, ...newOptions }
|
|
133
197
|
|
|
134
|
-
//
|
|
135
|
-
if (!this
|
|
136
|
-
this.
|
|
198
|
+
// Cancel pending execution if the debouncer is disabled
|
|
199
|
+
if (!this.#getEnabled()) {
|
|
200
|
+
this.cancel()
|
|
137
201
|
}
|
|
138
202
|
}
|
|
139
203
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
204
|
+
#setState = (newState: Partial<AsyncDebouncerState<TFn>>): void => {
|
|
205
|
+
this.store.setState((state) => {
|
|
206
|
+
const combinedState = {
|
|
207
|
+
...state,
|
|
208
|
+
...newState,
|
|
209
|
+
}
|
|
210
|
+
const { isPending, isExecuting, settleCount } = combinedState
|
|
211
|
+
return {
|
|
212
|
+
...combinedState,
|
|
213
|
+
status: !this.#getEnabled()
|
|
214
|
+
? 'disabled'
|
|
215
|
+
: isPending
|
|
216
|
+
? 'pending'
|
|
217
|
+
: isExecuting
|
|
218
|
+
? 'executing'
|
|
219
|
+
: settleCount > 0
|
|
220
|
+
? 'settled'
|
|
221
|
+
: 'idle',
|
|
222
|
+
}
|
|
223
|
+
})
|
|
145
224
|
}
|
|
146
225
|
|
|
147
226
|
/**
|
|
148
227
|
* Returns the current debouncer enabled state
|
|
149
228
|
*/
|
|
150
|
-
getEnabled(): boolean {
|
|
151
|
-
return !!parseFunctionOrValue(this.
|
|
229
|
+
#getEnabled = (): boolean => {
|
|
230
|
+
return !!parseFunctionOrValue(this.options.enabled, this)
|
|
152
231
|
}
|
|
153
232
|
|
|
154
233
|
/**
|
|
155
234
|
* Returns the current debouncer wait state
|
|
156
235
|
*/
|
|
157
|
-
getWait(): number {
|
|
158
|
-
return parseFunctionOrValue(this.
|
|
236
|
+
#getWait = (): number => {
|
|
237
|
+
return parseFunctionOrValue(this.options.wait, this)
|
|
159
238
|
}
|
|
160
239
|
|
|
161
240
|
/**
|
|
@@ -172,135 +251,126 @@ export class AsyncDebouncer<TFn extends AnyAsyncFunction> {
|
|
|
172
251
|
* @returns A promise that resolves with the function's return value, or undefined if an error occurred and was handled by onError
|
|
173
252
|
* @throws The error from the debounced function if no onError handler is configured
|
|
174
253
|
*/
|
|
175
|
-
async
|
|
254
|
+
maybeExecute = async (
|
|
176
255
|
...args: Parameters<TFn>
|
|
177
|
-
): Promise<ReturnType<TFn> | undefined> {
|
|
178
|
-
this
|
|
179
|
-
this
|
|
256
|
+
): Promise<ReturnType<TFn> | undefined> => {
|
|
257
|
+
if (!this.#getEnabled()) return undefined
|
|
258
|
+
this.#cancelPendingExecution()
|
|
259
|
+
this.#setState({ lastArgs: args })
|
|
180
260
|
|
|
181
261
|
// Handle leading execution
|
|
182
|
-
if (this.
|
|
183
|
-
this
|
|
184
|
-
await this
|
|
185
|
-
return this.
|
|
262
|
+
if (this.options.leading && this.store.state.canLeadingExecute) {
|
|
263
|
+
this.#setState({ canLeadingExecute: false })
|
|
264
|
+
await this.#execute(...args)
|
|
265
|
+
return this.store.state.lastResult
|
|
186
266
|
}
|
|
187
267
|
|
|
188
268
|
// Handle trailing execution
|
|
189
|
-
if (this.
|
|
190
|
-
this
|
|
269
|
+
if (this.options.trailing && this.#getEnabled()) {
|
|
270
|
+
this.#setState({ isPending: true })
|
|
191
271
|
}
|
|
192
272
|
|
|
193
273
|
return new Promise((resolve) => {
|
|
194
|
-
this
|
|
195
|
-
this
|
|
274
|
+
this.#resolvePreviousPromise = resolve
|
|
275
|
+
this.#timeoutId = setTimeout(async () => {
|
|
196
276
|
// Execute trailing if enabled
|
|
197
|
-
if (this.
|
|
198
|
-
await this
|
|
277
|
+
if (this.options.trailing && this.store.state.lastArgs) {
|
|
278
|
+
await this.#execute(...this.store.state.lastArgs)
|
|
199
279
|
}
|
|
200
280
|
|
|
201
281
|
// Reset state and resolve
|
|
202
|
-
this
|
|
203
|
-
this
|
|
204
|
-
resolve(this.
|
|
205
|
-
}, this
|
|
282
|
+
this.#setState({ canLeadingExecute: true })
|
|
283
|
+
this.#resolvePreviousPromise = null
|
|
284
|
+
resolve(this.store.state.lastResult)
|
|
285
|
+
}, this.#getWait())
|
|
206
286
|
})
|
|
207
287
|
}
|
|
208
288
|
|
|
209
|
-
|
|
289
|
+
#execute = async (
|
|
210
290
|
...args: Parameters<TFn>
|
|
211
|
-
): Promise<ReturnType<TFn> | undefined> {
|
|
212
|
-
if (!this
|
|
213
|
-
this
|
|
291
|
+
): Promise<ReturnType<TFn> | undefined> => {
|
|
292
|
+
if (!this.#getEnabled()) return undefined
|
|
293
|
+
this.#abortController = new AbortController()
|
|
214
294
|
try {
|
|
215
|
-
this
|
|
216
|
-
|
|
217
|
-
this
|
|
218
|
-
|
|
295
|
+
this.#setState({ isExecuting: true })
|
|
296
|
+
const result = await this.fn(...args) // EXECUTE!
|
|
297
|
+
this.#setState({
|
|
298
|
+
lastResult: result,
|
|
299
|
+
successCount: this.store.state.successCount + 1,
|
|
300
|
+
})
|
|
301
|
+
this.options.onSuccess?.(result, this)
|
|
219
302
|
} catch (error) {
|
|
220
|
-
this
|
|
221
|
-
|
|
222
|
-
|
|
303
|
+
this.#setState({
|
|
304
|
+
errorCount: this.store.state.errorCount + 1,
|
|
305
|
+
})
|
|
306
|
+
this.options.onError?.(error, this)
|
|
307
|
+
if (this.options.throwOnError) {
|
|
223
308
|
throw error
|
|
224
309
|
}
|
|
225
310
|
} finally {
|
|
226
|
-
this
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
311
|
+
this.#setState({
|
|
312
|
+
isExecuting: false,
|
|
313
|
+
isPending: false,
|
|
314
|
+
settleCount: this.store.state.settleCount + 1,
|
|
315
|
+
})
|
|
316
|
+
this.#abortController = null
|
|
317
|
+
this.options.onSettled?.(this)
|
|
231
318
|
}
|
|
232
|
-
return this.
|
|
319
|
+
return this.store.state.lastResult
|
|
233
320
|
}
|
|
234
321
|
|
|
235
322
|
/**
|
|
236
|
-
*
|
|
323
|
+
* Processes the current pending execution immediately
|
|
237
324
|
*/
|
|
238
|
-
|
|
239
|
-
if (this.
|
|
240
|
-
|
|
241
|
-
this
|
|
242
|
-
|
|
243
|
-
if (this._abortController) {
|
|
244
|
-
this._abortController.abort()
|
|
245
|
-
this._abortController = null
|
|
246
|
-
}
|
|
247
|
-
if (this._resolvePreviousPromise) {
|
|
248
|
-
this._resolvePreviousPromise(this._lastResult)
|
|
249
|
-
this._resolvePreviousPromise = null
|
|
325
|
+
flush = (): void => {
|
|
326
|
+
if (this.store.state.isPending && this.store.state.lastArgs) {
|
|
327
|
+
this.#abortExecution() // abort any current execution
|
|
328
|
+
this.#clearTimeout() // clear any existing timeout
|
|
329
|
+
this.#execute(...this.store.state.lastArgs)
|
|
250
330
|
}
|
|
251
|
-
this._lastArgs = undefined
|
|
252
|
-
this._isPending = false
|
|
253
|
-
this._isExecuting = false
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Cancels any pending execution or aborts any execution in progress
|
|
258
|
-
*/
|
|
259
|
-
cancel(): void {
|
|
260
|
-
this._canLeadingExecute = true
|
|
261
|
-
this._cancel()
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Returns the last result of the debounced function
|
|
266
|
-
*/
|
|
267
|
-
getLastResult(): ReturnType<TFn> | undefined {
|
|
268
|
-
return this._lastResult
|
|
269
331
|
}
|
|
270
332
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
333
|
+
#clearTimeout = (): void => {
|
|
334
|
+
if (this.#timeoutId) {
|
|
335
|
+
clearTimeout(this.#timeoutId)
|
|
336
|
+
this.#timeoutId = null
|
|
337
|
+
}
|
|
276
338
|
}
|
|
277
339
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
340
|
+
#cancelPendingExecution = (): void => {
|
|
341
|
+
this.#clearTimeout()
|
|
342
|
+
if (this.#resolvePreviousPromise) {
|
|
343
|
+
this.#resolvePreviousPromise(this.store.state.lastResult)
|
|
344
|
+
this.#resolvePreviousPromise = null
|
|
345
|
+
}
|
|
346
|
+
this.#setState({
|
|
347
|
+
isPending: false,
|
|
348
|
+
isExecuting: false,
|
|
349
|
+
lastArgs: undefined,
|
|
350
|
+
})
|
|
283
351
|
}
|
|
284
352
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
353
|
+
#abortExecution = (): void => {
|
|
354
|
+
if (this.#abortController) {
|
|
355
|
+
this.#abortController.abort()
|
|
356
|
+
this.#abortController = null
|
|
357
|
+
}
|
|
290
358
|
}
|
|
291
359
|
|
|
292
360
|
/**
|
|
293
|
-
*
|
|
361
|
+
* Cancels any pending execution or aborts any execution in progress
|
|
294
362
|
*/
|
|
295
|
-
|
|
296
|
-
|
|
363
|
+
cancel = (): void => {
|
|
364
|
+
this.#cancelPendingExecution()
|
|
365
|
+
this.#abortExecution()
|
|
366
|
+
this.#setState({ canLeadingExecute: true })
|
|
297
367
|
}
|
|
298
368
|
|
|
299
369
|
/**
|
|
300
|
-
*
|
|
370
|
+
* Resets the debouncer state to its default values
|
|
301
371
|
*/
|
|
302
|
-
|
|
303
|
-
|
|
372
|
+
reset = (): void => {
|
|
373
|
+
this.#setState(getDefaultAsyncDebouncerState<TFn>())
|
|
304
374
|
}
|
|
305
375
|
}
|
|
306
376
|
|
|
@@ -320,6 +390,16 @@ export class AsyncDebouncer<TFn extends AnyAsyncFunction> {
|
|
|
320
390
|
* - The error state can be checked using the underlying AsyncDebouncer instance
|
|
321
391
|
* - Both onError and throwOnError can be used together - the handler will be called before any error is thrown
|
|
322
392
|
*
|
|
393
|
+
* State Management:
|
|
394
|
+
* - Uses TanStack Store for reactive state management
|
|
395
|
+
* - Use `initialState` to provide initial state values when creating the async debouncer
|
|
396
|
+
* - Use `onSuccess` callback to react to successful function execution and implement custom logic
|
|
397
|
+
* - Use `onError` callback to react to function execution errors and implement custom error handling
|
|
398
|
+
* - Use `onSettled` callback to react to function execution completion (success or error) and implement custom logic
|
|
399
|
+
* - The state includes canLeadingExecute, error count, execution status, and success/settle counts
|
|
400
|
+
* - State can be accessed via `asyncDebouncer.store.state` when using the class directly
|
|
401
|
+
* - When using framework adapters (React/Solid), state is accessed from `asyncDebouncer.state`
|
|
402
|
+
*
|
|
323
403
|
* @example
|
|
324
404
|
* ```ts
|
|
325
405
|
* const debounced = asyncDebounce(async (value: string) => {
|
|
@@ -343,5 +423,5 @@ export function asyncDebounce<TFn extends AnyAsyncFunction>(
|
|
|
343
423
|
initialOptions: AsyncDebouncerOptions<TFn>,
|
|
344
424
|
) {
|
|
345
425
|
const asyncDebouncer = new AsyncDebouncer(fn, initialOptions)
|
|
346
|
-
return asyncDebouncer.maybeExecute
|
|
426
|
+
return asyncDebouncer.maybeExecute
|
|
347
427
|
}
|