@tanstack/pacer 0.1.0 → 0.3.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-debouncer.cjs +112 -63
- package/dist/cjs/async-debouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer.d.cts +66 -25
- package/dist/cjs/async-queuer.cjs +198 -124
- package/dist/cjs/async-queuer.cjs.map +1 -1
- package/dist/cjs/async-queuer.d.cts +91 -49
- package/dist/cjs/async-rate-limiter.cjs +83 -55
- package/dist/cjs/async-rate-limiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter.d.cts +55 -28
- package/dist/cjs/async-throttler.cjs +121 -70
- package/dist/cjs/async-throttler.cjs.map +1 -1
- package/dist/cjs/async-throttler.d.cts +75 -25
- package/dist/cjs/debouncer.cjs +45 -23
- package/dist/cjs/debouncer.cjs.map +1 -1
- package/dist/cjs/debouncer.d.cts +27 -12
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -0
- package/dist/cjs/queuer.cjs +161 -101
- package/dist/cjs/queuer.cjs.map +1 -1
- package/dist/cjs/queuer.d.cts +80 -38
- package/dist/cjs/rate-limiter.cjs +52 -44
- package/dist/cjs/rate-limiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter.d.cts +38 -46
- package/dist/cjs/throttler.cjs +57 -44
- package/dist/cjs/throttler.cjs.map +1 -1
- package/dist/cjs/throttler.d.cts +35 -23
- package/dist/cjs/types.d.cts +8 -0
- package/dist/cjs/utils.cjs +13 -0
- package/dist/cjs/utils.cjs.map +1 -0
- package/dist/cjs/utils.d.cts +1 -0
- package/dist/esm/async-debouncer.d.ts +66 -25
- package/dist/esm/async-debouncer.js +112 -63
- package/dist/esm/async-debouncer.js.map +1 -1
- package/dist/esm/async-queuer.d.ts +91 -49
- package/dist/esm/async-queuer.js +198 -124
- package/dist/esm/async-queuer.js.map +1 -1
- package/dist/esm/async-rate-limiter.d.ts +55 -28
- package/dist/esm/async-rate-limiter.js +83 -55
- package/dist/esm/async-rate-limiter.js.map +1 -1
- package/dist/esm/async-throttler.d.ts +75 -25
- package/dist/esm/async-throttler.js +121 -70
- package/dist/esm/async-throttler.js.map +1 -1
- package/dist/esm/debouncer.d.ts +27 -12
- package/dist/esm/debouncer.js +45 -23
- package/dist/esm/debouncer.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/queuer.d.ts +80 -38
- package/dist/esm/queuer.js +161 -101
- package/dist/esm/queuer.js.map +1 -1
- package/dist/esm/rate-limiter.d.ts +38 -46
- package/dist/esm/rate-limiter.js +52 -44
- package/dist/esm/rate-limiter.js.map +1 -1
- package/dist/esm/throttler.d.ts +35 -23
- package/dist/esm/throttler.js +57 -44
- package/dist/esm/throttler.js.map +1 -1
- package/dist/esm/types.d.ts +8 -0
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +13 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +8 -1
- package/src/async-debouncer.ts +157 -88
- package/src/async-queuer.ts +266 -148
- package/src/async-rate-limiter.ts +123 -83
- package/src/async-throttler.ts +173 -89
- package/src/debouncer.ts +71 -42
- package/src/index.ts +2 -0
- package/src/queuer.ts +219 -114
- package/src/rate-limiter.ts +74 -88
- package/src/throttler.ts +83 -65
- package/src/types.ts +9 -0
- package/src/utils.ts +13 -0
package/src/debouncer.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { AnyFunction } from './types'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Options for configuring a debounced function
|
|
3
5
|
*/
|
|
4
|
-
export interface DebouncerOptions {
|
|
6
|
+
export interface DebouncerOptions<TFn extends AnyFunction> {
|
|
5
7
|
/**
|
|
6
8
|
* Whether the debouncer is enabled. When disabled, maybeExecute will not trigger any executions.
|
|
7
9
|
* Defaults to true.
|
|
@@ -9,9 +11,14 @@ export interface DebouncerOptions {
|
|
|
9
11
|
enabled?: boolean
|
|
10
12
|
/**
|
|
11
13
|
* Whether to execute on the leading edge of the timeout.
|
|
14
|
+
* The first call will execute immediately and the rest will wait the delay.
|
|
12
15
|
* Defaults to false.
|
|
13
16
|
*/
|
|
14
17
|
leading?: boolean
|
|
18
|
+
/**
|
|
19
|
+
* Callback function that is called after the function is executed
|
|
20
|
+
*/
|
|
21
|
+
onExecute?: (debouncer: Debouncer<TFn>) => void
|
|
15
22
|
/**
|
|
16
23
|
* Whether to execute on the trailing edge of the timeout.
|
|
17
24
|
* Defaults to true.
|
|
@@ -24,9 +31,10 @@ export interface DebouncerOptions {
|
|
|
24
31
|
wait: number
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
const defaultOptions: Required<DebouncerOptions
|
|
34
|
+
const defaultOptions: Required<DebouncerOptions<any>> = {
|
|
28
35
|
enabled: true,
|
|
29
36
|
leading: false,
|
|
37
|
+
onExecute: () => {},
|
|
30
38
|
trailing: true,
|
|
31
39
|
wait: 0,
|
|
32
40
|
}
|
|
@@ -54,20 +62,18 @@ const defaultOptions: Required<DebouncerOptions> = {
|
|
|
54
62
|
* });
|
|
55
63
|
* ```
|
|
56
64
|
*/
|
|
57
|
-
export class Debouncer<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
private
|
|
63
|
-
private options: Required<DebouncerOptions>
|
|
64
|
-
private timeoutId: NodeJS.Timeout | undefined
|
|
65
|
+
export class Debouncer<TFn extends AnyFunction> {
|
|
66
|
+
private _canLeadingExecute = true
|
|
67
|
+
private _executionCount = 0
|
|
68
|
+
private _isPending = false
|
|
69
|
+
private _options: Required<DebouncerOptions<TFn>>
|
|
70
|
+
private _timeoutId: NodeJS.Timeout | undefined
|
|
65
71
|
|
|
66
72
|
constructor(
|
|
67
73
|
private fn: TFn,
|
|
68
|
-
initialOptions: DebouncerOptions
|
|
74
|
+
initialOptions: DebouncerOptions<TFn>,
|
|
69
75
|
) {
|
|
70
|
-
this.
|
|
76
|
+
this._options = {
|
|
71
77
|
...defaultOptions,
|
|
72
78
|
...initialOptions,
|
|
73
79
|
}
|
|
@@ -77,62 +83,85 @@ export class Debouncer<
|
|
|
77
83
|
* Updates the debouncer options
|
|
78
84
|
* Returns the new options state
|
|
79
85
|
*/
|
|
80
|
-
setOptions(
|
|
81
|
-
newOptions
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
setOptions(newOptions: Partial<DebouncerOptions<TFn>>): void {
|
|
87
|
+
this._options = { ...this._options, ...newOptions }
|
|
88
|
+
|
|
89
|
+
// End the pending state if the debouncer is disabled
|
|
90
|
+
if (!this._options.enabled) {
|
|
91
|
+
this._isPending = false
|
|
86
92
|
}
|
|
87
|
-
return this.options
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
/**
|
|
91
|
-
* Returns the
|
|
96
|
+
* Returns the current debouncer options
|
|
92
97
|
*/
|
|
93
|
-
|
|
94
|
-
return this.
|
|
98
|
+
getOptions(): Required<DebouncerOptions<TFn>> {
|
|
99
|
+
return this._options
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
/**
|
|
98
103
|
* Attempts to execute the debounced function
|
|
99
104
|
* If a call is already in progress, it will be queued
|
|
100
105
|
*/
|
|
101
|
-
maybeExecute(...args:
|
|
106
|
+
maybeExecute(...args: Parameters<TFn>): void {
|
|
107
|
+
let _didLeadingExecute = false
|
|
108
|
+
|
|
102
109
|
// Handle leading execution
|
|
103
|
-
if (this.
|
|
110
|
+
if (this._options.leading && this._canLeadingExecute) {
|
|
111
|
+
this._canLeadingExecute = false
|
|
112
|
+
_didLeadingExecute = true
|
|
104
113
|
this.executeFunction(...args)
|
|
105
|
-
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Start pending state to indicate that the debouncer is waiting for the trailing edge
|
|
117
|
+
if (this._options.trailing) {
|
|
118
|
+
this._isPending = true
|
|
106
119
|
}
|
|
107
120
|
|
|
108
121
|
// Clear any existing timeout
|
|
109
|
-
if (this.
|
|
122
|
+
if (this._timeoutId) clearTimeout(this._timeoutId)
|
|
110
123
|
|
|
111
|
-
// Set new timeout that will reset canLeadingExecute
|
|
112
|
-
this.
|
|
113
|
-
this.
|
|
114
|
-
|
|
115
|
-
if (this.options.trailing) {
|
|
124
|
+
// Set new timeout that will reset canLeadingExecute and execute trailing only if enabled and did not execute leading
|
|
125
|
+
this._timeoutId = setTimeout(() => {
|
|
126
|
+
this._canLeadingExecute = true
|
|
127
|
+
if (this._options.trailing && !_didLeadingExecute) {
|
|
116
128
|
this.executeFunction(...args)
|
|
117
129
|
}
|
|
118
|
-
}, this.
|
|
130
|
+
}, this._options.wait)
|
|
119
131
|
}
|
|
120
132
|
|
|
121
|
-
private executeFunction(...args:
|
|
122
|
-
if (!this.
|
|
123
|
-
this.
|
|
124
|
-
this.
|
|
133
|
+
private executeFunction(...args: Parameters<TFn>): void {
|
|
134
|
+
if (!this._options.enabled) return undefined
|
|
135
|
+
this.fn(...args) // EXECUTE!
|
|
136
|
+
this._isPending = false
|
|
137
|
+
this._executionCount++
|
|
138
|
+
this._options.onExecute(this)
|
|
125
139
|
}
|
|
126
140
|
|
|
127
141
|
/**
|
|
128
142
|
* Cancels any pending execution
|
|
129
143
|
*/
|
|
130
144
|
cancel(): void {
|
|
131
|
-
if (this.
|
|
132
|
-
clearTimeout(this.
|
|
133
|
-
this.
|
|
145
|
+
if (this._timeoutId) {
|
|
146
|
+
clearTimeout(this._timeoutId)
|
|
147
|
+
this._canLeadingExecute = true
|
|
148
|
+
this._isPending = false
|
|
134
149
|
}
|
|
135
150
|
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Returns the number of times the function has been executed
|
|
154
|
+
*/
|
|
155
|
+
getExecutionCount(): number {
|
|
156
|
+
return this._executionCount
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Returns `true` if debouncing
|
|
161
|
+
*/
|
|
162
|
+
getIsPending(): boolean {
|
|
163
|
+
return this._options.enabled && this._isPending
|
|
164
|
+
}
|
|
136
165
|
}
|
|
137
166
|
|
|
138
167
|
/**
|
|
@@ -155,10 +184,10 @@ export class Debouncer<
|
|
|
155
184
|
* inputElement.addEventListener('input', debounced);
|
|
156
185
|
* ```
|
|
157
186
|
*/
|
|
158
|
-
export function debounce<TFn extends
|
|
187
|
+
export function debounce<TFn extends AnyFunction>(
|
|
159
188
|
fn: TFn,
|
|
160
|
-
initialOptions: Omit<DebouncerOptions
|
|
161
|
-
) {
|
|
189
|
+
initialOptions: Omit<DebouncerOptions<TFn>, 'enabled'>,
|
|
190
|
+
): (...args: Parameters<TFn>) => void {
|
|
162
191
|
const debouncer = new Debouncer(fn, initialOptions)
|
|
163
192
|
return debouncer.maybeExecute.bind(debouncer)
|
|
164
193
|
}
|