@tanstack/pacer 0.2.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.
Files changed (65) hide show
  1. package/dist/cjs/async-debouncer.cjs +78 -45
  2. package/dist/cjs/async-debouncer.cjs.map +1 -1
  3. package/dist/cjs/async-debouncer.d.cts +44 -16
  4. package/dist/cjs/async-queuer.cjs +53 -3
  5. package/dist/cjs/async-queuer.cjs.map +1 -1
  6. package/dist/cjs/async-queuer.d.cts +28 -3
  7. package/dist/cjs/async-rate-limiter.cjs +46 -35
  8. package/dist/cjs/async-rate-limiter.cjs.map +1 -1
  9. package/dist/cjs/async-rate-limiter.d.cts +34 -19
  10. package/dist/cjs/async-throttler.cjs +85 -57
  11. package/dist/cjs/async-throttler.cjs.map +1 -1
  12. package/dist/cjs/async-throttler.d.cts +49 -17
  13. package/dist/cjs/debouncer.cjs +12 -14
  14. package/dist/cjs/debouncer.cjs.map +1 -1
  15. package/dist/cjs/debouncer.d.cts +10 -9
  16. package/dist/cjs/queuer.cjs +51 -1
  17. package/dist/cjs/queuer.cjs.map +1 -1
  18. package/dist/cjs/queuer.d.cts +30 -1
  19. package/dist/cjs/rate-limiter.cjs +1 -5
  20. package/dist/cjs/rate-limiter.cjs.map +1 -1
  21. package/dist/cjs/rate-limiter.d.cts +9 -9
  22. package/dist/cjs/throttler.cjs +29 -36
  23. package/dist/cjs/throttler.cjs.map +1 -1
  24. package/dist/cjs/throttler.d.cts +16 -17
  25. package/dist/cjs/types.d.cts +2 -6
  26. package/dist/cjs/utils.cjs.map +1 -1
  27. package/dist/cjs/utils.d.cts +1 -1
  28. package/dist/esm/async-debouncer.d.ts +44 -16
  29. package/dist/esm/async-debouncer.js +78 -45
  30. package/dist/esm/async-debouncer.js.map +1 -1
  31. package/dist/esm/async-queuer.d.ts +28 -3
  32. package/dist/esm/async-queuer.js +53 -3
  33. package/dist/esm/async-queuer.js.map +1 -1
  34. package/dist/esm/async-rate-limiter.d.ts +34 -19
  35. package/dist/esm/async-rate-limiter.js +46 -35
  36. package/dist/esm/async-rate-limiter.js.map +1 -1
  37. package/dist/esm/async-throttler.d.ts +49 -17
  38. package/dist/esm/async-throttler.js +85 -57
  39. package/dist/esm/async-throttler.js.map +1 -1
  40. package/dist/esm/debouncer.d.ts +10 -9
  41. package/dist/esm/debouncer.js +12 -14
  42. package/dist/esm/debouncer.js.map +1 -1
  43. package/dist/esm/queuer.d.ts +30 -1
  44. package/dist/esm/queuer.js +51 -1
  45. package/dist/esm/queuer.js.map +1 -1
  46. package/dist/esm/rate-limiter.d.ts +9 -9
  47. package/dist/esm/rate-limiter.js +1 -5
  48. package/dist/esm/rate-limiter.js.map +1 -1
  49. package/dist/esm/throttler.d.ts +16 -17
  50. package/dist/esm/throttler.js +29 -36
  51. package/dist/esm/throttler.js.map +1 -1
  52. package/dist/esm/types.d.ts +2 -6
  53. package/dist/esm/utils.d.ts +1 -1
  54. package/dist/esm/utils.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/async-debouncer.ts +114 -73
  57. package/src/async-queuer.ts +93 -8
  58. package/src/async-rate-limiter.ts +74 -60
  59. package/src/async-throttler.ts +135 -86
  60. package/src/debouncer.ts +26 -33
  61. package/src/queuer.ts +92 -4
  62. package/src/rate-limiter.ts +14 -26
  63. package/src/throttler.ts +45 -53
  64. package/src/types.ts +2 -10
  65. package/src/utils.ts +1 -1
@@ -3,10 +3,7 @@ import type { AnyAsyncFunction } from './types'
3
3
  /**
4
4
  * Options for configuring an async rate-limited function
5
5
  */
6
- export interface AsyncRateLimiterOptions<
7
- TFn extends AnyAsyncFunction,
8
- TArgs extends Parameters<TFn>,
9
- > {
6
+ export interface AsyncRateLimiterOptions<TFn extends AnyAsyncFunction> {
10
7
  /**
11
8
  * Whether the rate limiter is enabled. When disabled, maybeExecute will not trigger any executions.
12
9
  * Defaults to true.
@@ -19,15 +16,22 @@ export interface AsyncRateLimiterOptions<
19
16
  /**
20
17
  * Optional error handler for when the rate-limited function throws
21
18
  */
22
- onError?: (error: unknown) => void
19
+ onError?: (error: unknown, rateLimiter: AsyncRateLimiter<TFn>) => void
23
20
  /**
24
21
  * Optional function to call when the rate-limited function is executed
25
22
  */
26
- onExecute?: (rateLimiter: AsyncRateLimiter<TFn, TArgs>) => void
23
+ onSettled?: (rateLimiter: AsyncRateLimiter<TFn>) => void
24
+ /**
25
+ * Optional function to call when the rate-limited function is executed
26
+ */
27
+ onSuccess?: (
28
+ result: ReturnType<TFn>,
29
+ rateLimiter: AsyncRateLimiter<TFn>,
30
+ ) => void
27
31
  /**
28
32
  * Optional callback function that is called when an execution is rejected due to rate limiting
29
33
  */
30
- onReject?: (rateLimiter: AsyncRateLimiter<TFn, TArgs>) => void
34
+ onReject?: (rateLimiter: AsyncRateLimiter<TFn>) => void
31
35
  /**
32
36
  * Time window in milliseconds within which the limit applies
33
37
  */
@@ -35,12 +39,13 @@ export interface AsyncRateLimiterOptions<
35
39
  }
36
40
 
37
41
  const defaultOptions: Required<
38
- Omit<AsyncRateLimiterOptions<any, any>, 'limit' | 'window'>
42
+ Omit<AsyncRateLimiterOptions<any>, 'limit' | 'window'>
39
43
  > = {
40
44
  enabled: true,
41
- onReject: () => {},
42
45
  onError: () => {},
43
- onExecute: () => {},
46
+ onReject: () => {},
47
+ onSettled: () => {},
48
+ onSuccess: () => {},
44
49
  }
45
50
 
46
51
  /**
@@ -68,18 +73,18 @@ const defaultOptions: Required<
68
73
  * await rateLimiter.maybeExecute('123');
69
74
  * ```
70
75
  */
71
- export class AsyncRateLimiter<
72
- TFn extends AnyAsyncFunction,
73
- TArgs extends Parameters<TFn>,
74
- > {
75
- private _executionCount = 0
76
+ export class AsyncRateLimiter<TFn extends AnyAsyncFunction> {
77
+ private _options: AsyncRateLimiterOptions<TFn>
78
+ private _errorCount = 0
76
79
  private _executionTimes: Array<number> = []
77
- private _options: AsyncRateLimiterOptions<TFn, TArgs>
80
+ private _lastResult: ReturnType<TFn> | undefined
78
81
  private _rejectionCount = 0
82
+ private _settleCount = 0
83
+ private _successCount = 0
79
84
 
80
85
  constructor(
81
86
  private fn: TFn,
82
- initialOptions: AsyncRateLimiterOptions<TFn, TArgs>,
87
+ initialOptions: AsyncRateLimiterOptions<TFn>,
83
88
  ) {
84
89
  this._options = {
85
90
  ...defaultOptions,
@@ -91,21 +96,15 @@ export class AsyncRateLimiter<
91
96
  * Updates the rate limiter options
92
97
  * Returns the new options state
93
98
  */
94
- setOptions(
95
- newOptions: Partial<AsyncRateLimiterOptions<TFn, TArgs>>,
96
- ): AsyncRateLimiterOptions<TFn, TArgs> {
97
- this._options = {
98
- ...this._options,
99
- ...newOptions,
100
- }
101
- return this._options
99
+ setOptions(newOptions: Partial<AsyncRateLimiterOptions<TFn>>): void {
100
+ this._options = { ...this._options, ...newOptions }
102
101
  }
103
102
 
104
103
  /**
105
104
  * Returns the current rate limiter options
106
105
  */
107
- getOptions(): Required<AsyncRateLimiterOptions<TFn, TArgs>> {
108
- return this._options as Required<AsyncRateLimiterOptions<TFn, TArgs>>
106
+ getOptions(): Required<AsyncRateLimiterOptions<TFn>> {
107
+ return this._options as Required<AsyncRateLimiterOptions<TFn>>
109
108
  }
110
109
 
111
110
  /**
@@ -124,38 +123,40 @@ export class AsyncRateLimiter<
124
123
  * await rateLimiter.maybeExecute('arg1', 'arg2'); // Rejected
125
124
  * ```
126
125
  */
127
- async maybeExecute(...args: TArgs): Promise<boolean> {
126
+ async maybeExecute(
127
+ ...args: Parameters<TFn>
128
+ ): Promise<ReturnType<TFn> | undefined> {
128
129
  this.cleanupOldExecutions()
129
130
 
130
131
  if (this._executionTimes.length < this._options.limit) {
131
132
  await this.executeFunction(...args)
132
- return true
133
+ return this._lastResult
133
134
  }
134
135
 
135
136
  this.rejectFunction()
136
- return false
137
+ return undefined
137
138
  }
138
139
 
139
- private async executeFunction(...args: TArgs): Promise<void> {
140
+ private async executeFunction(
141
+ ...args: Parameters<TFn>
142
+ ): Promise<ReturnType<TFn> | undefined> {
140
143
  if (!this._options.enabled) return
141
144
  const now = Date.now()
142
- this._executionCount++
143
145
  this._executionTimes.push(now)
144
146
 
145
147
  try {
146
- await this.fn(...args)
148
+ this._lastResult = await this.fn(...args)
149
+ this._successCount++
150
+ this._options.onSuccess?.(this._lastResult!, this)
147
151
  } catch (error) {
148
- if (this._options.onError) {
149
- try {
150
- this._options.onError(error)
151
- } catch (error) {
152
- console.error('Error in onError handler', error)
153
- }
154
- }
155
- throw error
152
+ this._errorCount++
153
+ this._options.onError?.(error, this)
156
154
  } finally {
157
- this._options.onExecute?.(this)
155
+ this._settleCount++
156
+ this._options.onSettled?.(this)
158
157
  }
158
+
159
+ return this._lastResult
159
160
  }
160
161
 
161
162
  private rejectFunction(): void {
@@ -173,33 +174,47 @@ export class AsyncRateLimiter<
173
174
  )
174
175
  }
175
176
 
177
+ /**
178
+ * Returns the number of remaining executions allowed in the current window
179
+ */
180
+ getRemainingInWindow(): number {
181
+ this.cleanupOldExecutions()
182
+ return Math.max(0, this._options.limit - this._executionTimes.length)
183
+ }
184
+
185
+ /**
186
+ * Returns the number of milliseconds until the next execution will be possible
187
+ */
188
+ getMsUntilNextWindow(): number {
189
+ return this.getRemainingInWindow() * this._options.window
190
+ }
191
+
176
192
  /**
177
193
  * Returns the number of times the function has been executed
178
194
  */
179
- getExecutionCount(): number {
180
- return this._executionCount
195
+ getSuccessCount(): number {
196
+ return this._successCount
181
197
  }
182
198
 
183
199
  /**
184
- * Returns the number of times the function has been rejected
200
+ * Returns the number of times the function has been settled
185
201
  */
186
- getRejectionCount(): number {
187
- return this._rejectionCount
202
+ getSettleCount(): number {
203
+ return this._settleCount
188
204
  }
189
205
 
190
206
  /**
191
- * Returns the number of remaining executions allowed in the current window
207
+ * Returns the number of times the function has errored
192
208
  */
193
- getRemainingInWindow(): number {
194
- this.cleanupOldExecutions()
195
- return Math.max(0, this._options.limit - this._executionTimes.length)
209
+ getErrorCount(): number {
210
+ return this._errorCount
196
211
  }
197
212
 
198
213
  /**
199
- * Returns the number of milliseconds until the next execution will be possible
214
+ * Returns the number of times the function has been rejected
200
215
  */
201
- getMsUntilNextWindow(): number {
202
- return this.getRemainingInWindow() * this._options.window
216
+ getRejectionCount(): number {
217
+ return this._rejectionCount
203
218
  }
204
219
 
205
220
  /**
@@ -207,8 +222,10 @@ export class AsyncRateLimiter<
207
222
  */
208
223
  reset(): void {
209
224
  this._executionTimes = []
210
- this._executionCount = 0
225
+ this._successCount = 0
226
+ this._errorCount = 0
211
227
  this._rejectionCount = 0
228
+ this._settleCount = 0
212
229
  }
213
230
  }
214
231
 
@@ -242,12 +259,9 @@ export class AsyncRateLimiter<
242
259
  * const throttled = throttle(makeApiCall, { wait: 12000 }); // One call every 12 seconds
243
260
  * ```
244
261
  */
245
- export function asyncRateLimit<
246
- TFn extends AnyAsyncFunction,
247
- TArgs extends Parameters<TFn>,
248
- >(
262
+ export function asyncRateLimit<TFn extends AnyAsyncFunction>(
249
263
  fn: TFn,
250
- initialOptions: Omit<AsyncRateLimiterOptions<TFn, TArgs>, 'enabled'>,
264
+ initialOptions: Omit<AsyncRateLimiterOptions<TFn>, 'enabled'>,
251
265
  ) {
252
266
  const rateLimiter = new AsyncRateLimiter(fn, initialOptions)
253
267
  return rateLimiter.maybeExecute.bind(rateLimiter)
@@ -3,23 +3,37 @@ import type { AnyAsyncFunction } from './types'
3
3
  /**
4
4
  * Options for configuring an async throttled function
5
5
  */
6
- export interface AsyncThrottlerOptions<
7
- TFn extends AnyAsyncFunction,
8
- TArgs extends Parameters<TFn>,
9
- > {
6
+ export interface AsyncThrottlerOptions<TFn extends AnyAsyncFunction> {
10
7
  /**
11
8
  * Whether the throttler is enabled. When disabled, maybeExecute will not trigger any executions.
12
9
  * Defaults to true.
13
10
  */
14
11
  enabled?: boolean
12
+ /**
13
+ * Whether to execute the function immediately when called
14
+ * Defaults to true
15
+ */
16
+ leading?: boolean
15
17
  /**
16
18
  * Optional error handler for when the throttled function throws
17
19
  */
18
- onError?: (error: unknown) => void
20
+ onError?: (error: unknown, asyncThrottler: AsyncThrottler<TFn>) => void
19
21
  /**
20
22
  * Optional function to call when the throttled function is executed
21
23
  */
22
- onExecute?: (throttler: AsyncThrottler<TFn, TArgs>) => void
24
+ onSettled?: (asyncThrottler: AsyncThrottler<TFn>) => void
25
+ /**
26
+ * Optional function to call when the throttled function is executed
27
+ */
28
+ onSuccess?: (
29
+ result: ReturnType<TFn>,
30
+ asyncThrottler: AsyncThrottler<TFn>,
31
+ ) => void
32
+ /**
33
+ * Whether to execute the function on the trailing edge of the wait period
34
+ * Defaults to true
35
+ */
36
+ trailing?: boolean
23
37
  /**
24
38
  * Time window in milliseconds during which the function can only be executed once
25
39
  * Defaults to 0ms
@@ -27,10 +41,13 @@ export interface AsyncThrottlerOptions<
27
41
  wait: number
28
42
  }
29
43
 
30
- const defaultOptions: Required<AsyncThrottlerOptions<any, any>> = {
44
+ const defaultOptions: Required<AsyncThrottlerOptions<any>> = {
31
45
  enabled: true,
46
+ leading: true,
32
47
  onError: () => {},
33
- onExecute: () => {},
48
+ onSettled: () => {},
49
+ onSuccess: () => {},
50
+ trailing: true,
34
51
  wait: 0,
35
52
  }
36
53
 
@@ -56,22 +73,22 @@ const defaultOptions: Required<AsyncThrottlerOptions<any, any>> = {
56
73
  * });
57
74
  * ```
58
75
  */
59
- export class AsyncThrottler<
60
- TFn extends AnyAsyncFunction,
61
- TArgs extends Parameters<TFn>,
62
- > {
63
- private _options: Required<AsyncThrottlerOptions<TFn, TArgs>>
76
+ export class AsyncThrottler<TFn extends AnyAsyncFunction> {
77
+ private _options: Required<AsyncThrottlerOptions<TFn>>
64
78
  private _abortController: AbortController | null = null
65
- private _executionCount = 0
79
+ private _errorCount = 0
66
80
  private _isExecuting = false
67
- private _isPending = false
68
- private _lastArgs: TArgs | undefined
81
+ private _lastArgs: Parameters<TFn> | undefined
69
82
  private _lastExecutionTime = 0
83
+ private _lastResult: ReturnType<TFn> | undefined
70
84
  private _nextExecutionTime = 0
85
+ private _settleCount = 0
86
+ private _successCount = 0
87
+ private _timeoutId: NodeJS.Timeout | null = null
71
88
 
72
89
  constructor(
73
90
  private fn: TFn,
74
- initialOptions: AsyncThrottlerOptions<TFn, TArgs>,
91
+ initialOptions: AsyncThrottlerOptions<TFn>,
75
92
  ) {
76
93
  this._options = {
77
94
  ...defaultOptions,
@@ -83,20 +100,19 @@ export class AsyncThrottler<
83
100
  * Updates the throttler options
84
101
  * Returns the new options state
85
102
  */
86
- setOptions(
87
- newOptions: Partial<AsyncThrottlerOptions<TFn, TArgs>>,
88
- ): Required<AsyncThrottlerOptions<TFn, TArgs>> {
89
- this._options = {
90
- ...this._options,
91
- ...newOptions,
103
+ setOptions(newOptions: Partial<AsyncThrottlerOptions<TFn>>): void {
104
+ this._options = { ...this._options, ...newOptions }
105
+
106
+ // End the pending state if the debouncer is disabled
107
+ if (!this._options.enabled) {
108
+ this.cancel()
92
109
  }
93
- return this._options
94
110
  }
95
111
 
96
112
  /**
97
113
  * Returns the current options
98
114
  */
99
- getOptions(): Required<AsyncThrottlerOptions<TFn, TArgs>> {
115
+ getOptions(): Required<AsyncThrottlerOptions<TFn>> {
100
116
  return this._options
101
117
  }
102
118
 
@@ -104,84 +120,82 @@ export class AsyncThrottler<
104
120
  * Attempts to execute the throttled function
105
121
  * If a call is already in progress, it may be blocked or queued depending on the `wait` option
106
122
  */
107
- async maybeExecute(...args: TArgs): Promise<void> {
108
- this._lastArgs = args
109
- if (this._isPending) return
110
- this._isPending = true
123
+ async maybeExecute(
124
+ ...args: Parameters<TFn>
125
+ ): Promise<ReturnType<TFn> | undefined> {
126
+ const now = Date.now()
127
+ const timeSinceLastExecution = now - this._lastExecutionTime
111
128
 
112
- this._abortController = new AbortController()
113
- const signal = this._abortController.signal
129
+ // Handle leading execution
130
+ if (this._options.leading && timeSinceLastExecution >= this._options.wait) {
131
+ await this.executeFunction(...args)
132
+ return this._lastResult
133
+ } else {
134
+ // Store the most recent arguments for potential trailing execution
135
+ this._lastArgs = args
114
136
 
115
- try {
116
- while (this._isExecuting) {
117
- await this.delay(this._options.wait, signal)
118
- }
137
+ return new Promise((resolve) => {
138
+ // Clear any existing timeout to ensure we use the latest arguments
139
+ if (this._timeoutId) {
140
+ clearTimeout(this._timeoutId)
141
+ }
119
142
 
120
- while (Date.now() < this._nextExecutionTime) {
121
- await this.delay(this._nextExecutionTime - Date.now(), signal)
122
- }
143
+ // Set up trailing execution if enabled
144
+ if (this._options.trailing) {
145
+ const _timeSinceLastExecution = this._lastExecutionTime
146
+ ? now - this._lastExecutionTime
147
+ : 0
148
+ const timeoutDuration = this._options.wait - _timeSinceLastExecution
149
+ this._timeoutId = setTimeout(async () => {
150
+ if (this._lastArgs !== undefined) {
151
+ await this.executeFunction(...this._lastArgs)
152
+ }
153
+ resolve(this._lastResult)
154
+ }, timeoutDuration)
155
+ }
156
+ })
157
+ }
158
+ }
123
159
 
124
- this._isPending = false
160
+ private async executeFunction(
161
+ ...args: Parameters<TFn>
162
+ ): Promise<ReturnType<TFn> | undefined> {
163
+ if (!this._options.enabled || this._isExecuting) return undefined
164
+ this._abortController = new AbortController()
165
+ try {
125
166
  this._isExecuting = true
126
-
127
- await this.executeFunction(...this._lastArgs)
167
+ this._lastResult = await this.fn(...args) // EXECUTE!
168
+ this._successCount++
169
+ this._options.onSuccess(this._lastResult!, this)
128
170
  } catch (error) {
129
- if (error instanceof Error && error.name === 'AbortError') {
130
- return // Silent return on cancellation
131
- }
132
- try {
133
- this._options.onError(error)
134
- } catch {
135
- // Ignore errors from error handler
136
- }
171
+ this._errorCount++
172
+ this._options.onError(error, this)
137
173
  } finally {
138
- this._lastExecutionTime = Date.now()
139
- this._nextExecutionTime = this._lastExecutionTime + this._options.wait
140
174
  this._isExecuting = false
175
+ this._settleCount++
141
176
  this._abortController = null
177
+ this._lastExecutionTime = Date.now()
178
+ this._nextExecutionTime = this._lastExecutionTime + this._options.wait
179
+ this._options.onSettled(this)
142
180
  }
143
- }
144
-
145
- private delay(ms: number, signal: AbortSignal): Promise<void> {
146
- return new Promise((resolve, reject) => {
147
- const timeout = setTimeout(resolve, ms)
148
- signal.addEventListener(
149
- 'abort',
150
- () => {
151
- clearTimeout(timeout)
152
- reject(new Error('AbortError'))
153
- },
154
- { once: true },
155
- )
156
- })
157
- }
158
-
159
- private async executeFunction(...args: TArgs): Promise<void> {
160
- if (!this._options.enabled) return
161
- this._executionCount++
162
- await this.fn(...args)
163
- this._options.onExecute(this)
181
+ return this._lastResult
164
182
  }
165
183
 
166
184
  /**
167
- * Cancels any pending execution
185
+ * Cancels any pending execution or aborts any execution in progress
168
186
  */
169
187
  cancel(): void {
188
+ if (this._timeoutId) {
189
+ clearTimeout(this._timeoutId)
190
+ this._timeoutId = null
191
+ }
170
192
  if (this._abortController) {
171
193
  this._abortController.abort()
172
194
  this._abortController = null
173
195
  }
174
- this._isPending = false
175
196
  this._lastArgs = undefined
176
197
  }
177
198
 
178
- /**
179
- * Returns the number of times the function has been executed
180
- */
181
- getExecutionCount(): number {
182
- return this._executionCount
183
- }
184
-
185
199
  /**
186
200
  * Returns the last execution time
187
201
  */
@@ -196,11 +210,46 @@ export class AsyncThrottler<
196
210
  return this._nextExecutionTime
197
211
  }
198
212
 
213
+ /**
214
+ * Returns the last result of the debounced function
215
+ */
216
+ getLastResult(): ReturnType<TFn> | undefined {
217
+ return this._lastResult
218
+ }
219
+
220
+ /**
221
+ * Returns the number of times the function has been executed successfully
222
+ */
223
+ getSuccessCount(): number {
224
+ return this._successCount
225
+ }
226
+
227
+ /**
228
+ * Returns the number of times the function has settled (completed or errored)
229
+ */
230
+ getSettleCount(): number {
231
+ return this._settleCount
232
+ }
233
+
234
+ /**
235
+ * Returns the number of times the function has errored
236
+ */
237
+ getErrorCount(): number {
238
+ return this._errorCount
239
+ }
240
+
199
241
  /**
200
242
  * Returns the current pending state
201
243
  */
202
244
  getIsPending(): boolean {
203
- return this._isPending
245
+ return this._options.enabled && !!this._timeoutId
246
+ }
247
+
248
+ /**
249
+ * Returns the current executing state
250
+ */
251
+ getIsExecuting(): boolean {
252
+ return this._isExecuting
204
253
  }
205
254
  }
206
255
 
@@ -220,10 +269,10 @@ export class AsyncThrottler<
220
269
  * await throttled(); // Waits 1 second before executing
221
270
  * ```
222
271
  */
223
- export function asyncThrottle<
224
- TFn extends AnyAsyncFunction,
225
- TArgs extends Parameters<TFn>,
226
- >(fn: TFn, initialOptions: Omit<AsyncThrottlerOptions<TFn, TArgs>, 'enabled'>) {
272
+ export function asyncThrottle<TFn extends AnyAsyncFunction>(
273
+ fn: TFn,
274
+ initialOptions: Omit<AsyncThrottlerOptions<TFn>, 'enabled'>,
275
+ ) {
227
276
  const asyncThrottler = new AsyncThrottler(fn, initialOptions)
228
277
  return asyncThrottler.maybeExecute.bind(asyncThrottler)
229
278
  }