@tanstack/pacer 0.6.0 → 0.7.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 +10 -6
- package/dist/cjs/async-debouncer.cjs.map +1 -1
- package/dist/cjs/async-debouncer.d.cts +2 -2
- package/dist/cjs/async-queuer.cjs +135 -106
- package/dist/cjs/async-queuer.cjs.map +1 -1
- package/dist/cjs/async-queuer.d.cts +121 -93
- package/dist/cjs/async-rate-limiter.cjs +3 -4
- package/dist/cjs/async-rate-limiter.cjs.map +1 -1
- package/dist/cjs/async-rate-limiter.d.cts +1 -2
- package/dist/cjs/async-throttler.cjs +14 -4
- package/dist/cjs/async-throttler.cjs.map +1 -1
- package/dist/cjs/async-throttler.d.cts +3 -2
- package/dist/cjs/batcher.cjs +138 -0
- package/dist/cjs/batcher.cjs.map +1 -0
- package/dist/cjs/batcher.d.cts +149 -0
- package/dist/cjs/debouncer.cjs +3 -4
- package/dist/cjs/debouncer.cjs.map +1 -1
- package/dist/cjs/debouncer.d.cts +1 -2
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/queuer.cjs +68 -41
- package/dist/cjs/queuer.cjs.map +1 -1
- package/dist/cjs/queuer.d.cts +123 -92
- package/dist/cjs/rate-limiter.cjs +3 -4
- package/dist/cjs/rate-limiter.cjs.map +1 -1
- package/dist/cjs/rate-limiter.d.cts +1 -2
- package/dist/cjs/throttler.cjs +3 -4
- package/dist/cjs/throttler.cjs.map +1 -1
- package/dist/cjs/throttler.d.cts +1 -2
- package/dist/esm/async-debouncer.d.ts +2 -2
- package/dist/esm/async-debouncer.js +10 -6
- package/dist/esm/async-debouncer.js.map +1 -1
- package/dist/esm/async-queuer.d.ts +121 -93
- package/dist/esm/async-queuer.js +135 -106
- package/dist/esm/async-queuer.js.map +1 -1
- package/dist/esm/async-rate-limiter.d.ts +1 -2
- package/dist/esm/async-rate-limiter.js +3 -4
- package/dist/esm/async-rate-limiter.js.map +1 -1
- package/dist/esm/async-throttler.d.ts +3 -2
- package/dist/esm/async-throttler.js +14 -4
- package/dist/esm/async-throttler.js.map +1 -1
- package/dist/esm/batcher.d.ts +149 -0
- package/dist/esm/batcher.js +138 -0
- package/dist/esm/batcher.js.map +1 -0
- package/dist/esm/debouncer.d.ts +1 -2
- package/dist/esm/debouncer.js +3 -4
- package/dist/esm/debouncer.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/queuer.d.ts +123 -92
- package/dist/esm/queuer.js +68 -41
- package/dist/esm/queuer.js.map +1 -1
- package/dist/esm/rate-limiter.d.ts +1 -2
- package/dist/esm/rate-limiter.js +3 -4
- package/dist/esm/rate-limiter.js.map +1 -1
- package/dist/esm/throttler.d.ts +1 -2
- package/dist/esm/throttler.js +3 -4
- package/dist/esm/throttler.js.map +1 -1
- package/package.json +11 -1
- package/src/async-debouncer.ts +12 -6
- package/src/async-queuer.ts +216 -193
- package/src/async-rate-limiter.ts +3 -4
- package/src/async-throttler.ts +18 -4
- package/src/batcher.ts +253 -0
- package/src/debouncer.ts +3 -4
- package/src/index.ts +1 -0
- package/src/queuer.ts +142 -98
- package/src/rate-limiter.ts +3 -4
- package/src/throttler.ts +3 -4
package/src/queuer.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { parseFunctionOrValue } from './utils'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Options for configuring a Queuer instance
|
|
4
|
+
* Options for configuring a Queuer instance.
|
|
5
|
+
*
|
|
6
|
+
* These options control queue behavior, item expiration, callbacks, and more.
|
|
5
7
|
*/
|
|
6
8
|
export interface QueuerOptions<TValue> {
|
|
7
9
|
/**
|
|
@@ -44,7 +46,7 @@ export interface QueuerOptions<TValue> {
|
|
|
44
46
|
/**
|
|
45
47
|
* Callback fired whenever an item is removed from the queuer
|
|
46
48
|
*/
|
|
47
|
-
|
|
49
|
+
onExecute?: (item: TValue, queuer: Queuer<TValue>) => void
|
|
48
50
|
/**
|
|
49
51
|
* Callback fired whenever the queuer's running state changes
|
|
50
52
|
*/
|
|
@@ -77,7 +79,7 @@ const defaultOptions: Required<QueuerOptions<any>> = {
|
|
|
77
79
|
expirationDuration: Infinity,
|
|
78
80
|
initialItems: [],
|
|
79
81
|
maxSize: Infinity,
|
|
80
|
-
|
|
82
|
+
onExecute: () => {},
|
|
81
83
|
onIsRunningChange: () => {},
|
|
82
84
|
onItemsChange: () => {},
|
|
83
85
|
onReject: () => {},
|
|
@@ -87,62 +89,72 @@ const defaultOptions: Required<QueuerOptions<any>> = {
|
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
/**
|
|
90
|
-
* Position type for addItem and getNextItem operations
|
|
92
|
+
* Position type for addItem and getNextItem operations.
|
|
93
|
+
*
|
|
94
|
+
* - 'front': Operate on the front of the queue (FIFO)
|
|
95
|
+
* - 'back': Operate on the back of the queue (LIFO)
|
|
91
96
|
*/
|
|
92
97
|
export type QueuePosition = 'front' | 'back'
|
|
93
98
|
|
|
94
99
|
/**
|
|
95
|
-
* A flexible queue
|
|
96
|
-
* with optional position overrides for stack-like or double-ended operations.
|
|
100
|
+
* A flexible queue that processes items with configurable wait times, expiration, and priority.
|
|
97
101
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
102
|
+
* Features:
|
|
103
|
+
* - Automatic or manual processing of items
|
|
104
|
+
* - FIFO (First In First Out), LIFO (Last In First Out), or double-ended queue behavior
|
|
105
|
+
* - Priority-based ordering when getPriority is provided
|
|
106
|
+
* - Item expiration and removal of stale items
|
|
107
|
+
* - Callbacks for queue state changes, execution, rejection, and expiration
|
|
101
108
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
109
|
+
* Running behavior:
|
|
110
|
+
* - `start()`: Begins automatically processing items in the queue (defaults to running)
|
|
111
|
+
* - `stop()`: Pauses processing but maintains queue state
|
|
112
|
+
* - `wait`: Configurable delay between processing items
|
|
113
|
+
* - `onItemsChange`/`onExecute`: Callbacks for monitoring queue state
|
|
104
114
|
*
|
|
105
|
-
*
|
|
106
|
-
* -
|
|
107
|
-
* - getNextItem()
|
|
115
|
+
* Manual processing is also supported when automatic processing is disabled:
|
|
116
|
+
* - `execute()`: Processes the next item using the provided function
|
|
117
|
+
* - `getNextItem()`: Removes and returns the next item without processing
|
|
108
118
|
*
|
|
109
|
-
*
|
|
110
|
-
* - addItem(item
|
|
111
|
-
* -
|
|
119
|
+
* Queue behavior defaults to FIFO:
|
|
120
|
+
* - `addItem(item)`: Adds to the back of the queue
|
|
121
|
+
* - Items processed from the front of the queue
|
|
112
122
|
*
|
|
113
|
-
*
|
|
114
|
-
* -
|
|
115
|
-
* - getNextItem(position): removes and returns from specified position
|
|
123
|
+
* Priority queue:
|
|
124
|
+
* - Provide a `getPriority` function; higher values are processed first
|
|
116
125
|
*
|
|
117
|
-
*
|
|
118
|
-
* -
|
|
119
|
-
* -
|
|
120
|
-
* - wait: configurable delay between processing items
|
|
121
|
-
* - onItemsChange/onGetNextItem: callbacks for monitoring queuer state
|
|
126
|
+
* Stack (LIFO):
|
|
127
|
+
* - `addItem(item, 'back')`: Adds to the back
|
|
128
|
+
* - `getNextItem('back')`: Removes from the back
|
|
122
129
|
*
|
|
123
|
-
*
|
|
124
|
-
* -
|
|
125
|
-
* -
|
|
126
|
-
* - onExpire: callback for when an item expires
|
|
130
|
+
* Double-ended queue:
|
|
131
|
+
* - `addItem(item, position)`: Adds to specified position ('front'/'back')
|
|
132
|
+
* - `getNextItem(position)`: Removes from specified position
|
|
127
133
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* queuer.addItem(1); // [1]
|
|
133
|
-
* queuer.addItem(2); // [1, 2]
|
|
134
|
-
* queuer.getNextItem(); // returns 1, queuer is [2]
|
|
134
|
+
* Item expiration:
|
|
135
|
+
* - `expirationDuration`: Maximum time items can stay in the queue
|
|
136
|
+
* - `getIsExpired`: Function to override default expiration
|
|
137
|
+
* - `onExpire`: Callback for expired items
|
|
135
138
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
+
* Example usage:
|
|
140
|
+
* ```ts
|
|
141
|
+
* // Auto-processing queue with wait time
|
|
142
|
+
* const autoQueue = new Queuer<number>((n) => console.log(n), {
|
|
139
143
|
* started: true, // Begin processing immediately
|
|
140
144
|
* wait: 1000, // Wait 1s between items
|
|
141
|
-
*
|
|
145
|
+
* onExecute: (item) => console.log(`Processed ${item}`)
|
|
142
146
|
* });
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
147
|
+
* autoQueue.addItem(1); // Will process after 1s
|
|
148
|
+
* autoQueue.addItem(2); // Will process 1s after first item
|
|
149
|
+
*
|
|
150
|
+
* // Manual processing queue
|
|
151
|
+
* const manualQueue = new Queuer<number>((n) => console.log(n), {
|
|
152
|
+
* started: false
|
|
153
|
+
* });
|
|
154
|
+
* manualQueue.addItem(1); // [1]
|
|
155
|
+
* manualQueue.addItem(2); // [1, 2]
|
|
156
|
+
* manualQueue.execute(); // logs 1, queue is [2]
|
|
157
|
+
* manualQueue.getNextItem(); // returns 2, queue is empty
|
|
146
158
|
* ```
|
|
147
159
|
*/
|
|
148
160
|
export class Queuer<TValue> {
|
|
@@ -156,7 +168,10 @@ export class Queuer<TValue> {
|
|
|
156
168
|
private _running: boolean
|
|
157
169
|
private _pendingTick = false
|
|
158
170
|
|
|
159
|
-
constructor(
|
|
171
|
+
constructor(
|
|
172
|
+
private fn: (item: TValue) => void,
|
|
173
|
+
initialOptions: QueuerOptions<TValue> = {},
|
|
174
|
+
) {
|
|
160
175
|
this._options = { ...defaultOptions, ...initialOptions }
|
|
161
176
|
this._running = this._options.started
|
|
162
177
|
|
|
@@ -168,29 +183,29 @@ export class Queuer<TValue> {
|
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
/**
|
|
171
|
-
* Updates the queuer options
|
|
172
|
-
* Returns the new options state
|
|
186
|
+
* Updates the queuer options. New options are merged with existing options.
|
|
173
187
|
*/
|
|
174
188
|
setOptions(newOptions: Partial<QueuerOptions<TValue>>): void {
|
|
175
189
|
this._options = { ...this._options, ...newOptions }
|
|
176
190
|
}
|
|
177
191
|
|
|
178
192
|
/**
|
|
179
|
-
* Returns the current queuer options
|
|
193
|
+
* Returns the current queuer options, including defaults and any overrides.
|
|
180
194
|
*/
|
|
181
195
|
getOptions(): Required<QueuerOptions<TValue>> {
|
|
182
196
|
return this._options
|
|
183
197
|
}
|
|
184
198
|
|
|
185
199
|
/**
|
|
186
|
-
* Returns the current wait time in milliseconds
|
|
200
|
+
* Returns the current wait time (in milliseconds) between processing items.
|
|
201
|
+
* If a function is provided, it is called with the queuer instance.
|
|
187
202
|
*/
|
|
188
203
|
getWait(): number {
|
|
189
204
|
return parseFunctionOrValue(this._options.wait, this)
|
|
190
205
|
}
|
|
191
206
|
|
|
192
207
|
/**
|
|
193
|
-
* Processes items in the
|
|
208
|
+
* Processes items in the queue up to the wait interval. Internal use only.
|
|
194
209
|
*/
|
|
195
210
|
private tick() {
|
|
196
211
|
if (!this._running) {
|
|
@@ -202,7 +217,7 @@ export class Queuer<TValue> {
|
|
|
202
217
|
this.checkExpiredItems()
|
|
203
218
|
|
|
204
219
|
while (!this.getIsEmpty()) {
|
|
205
|
-
const nextItem = this.
|
|
220
|
+
const nextItem = this.execute(this._options.getItemsFrom)
|
|
206
221
|
if (nextItem === undefined) {
|
|
207
222
|
break
|
|
208
223
|
}
|
|
@@ -221,7 +236,8 @@ export class Queuer<TValue> {
|
|
|
221
236
|
}
|
|
222
237
|
|
|
223
238
|
/**
|
|
224
|
-
* Checks for and removes
|
|
239
|
+
* Checks for expired items in the queue and removes them. Calls onExpire for each expired item.
|
|
240
|
+
* Internal use only.
|
|
225
241
|
*/
|
|
226
242
|
private checkExpiredItems() {
|
|
227
243
|
if (
|
|
@@ -271,7 +287,7 @@ export class Queuer<TValue> {
|
|
|
271
287
|
}
|
|
272
288
|
|
|
273
289
|
/**
|
|
274
|
-
* Stops the
|
|
290
|
+
* Stops processing items in the queue. Does not clear the queue.
|
|
275
291
|
*/
|
|
276
292
|
stop() {
|
|
277
293
|
this._running = false
|
|
@@ -280,7 +296,7 @@ export class Queuer<TValue> {
|
|
|
280
296
|
}
|
|
281
297
|
|
|
282
298
|
/**
|
|
283
|
-
* Starts the
|
|
299
|
+
* Starts processing items in the queue. If already running, does nothing.
|
|
284
300
|
*/
|
|
285
301
|
start() {
|
|
286
302
|
this._running = true
|
|
@@ -292,7 +308,7 @@ export class Queuer<TValue> {
|
|
|
292
308
|
}
|
|
293
309
|
|
|
294
310
|
/**
|
|
295
|
-
* Removes all items from the
|
|
311
|
+
* Removes all pending items from the queue. Does not affect items being processed.
|
|
296
312
|
*/
|
|
297
313
|
clear(): void {
|
|
298
314
|
this._items = []
|
|
@@ -300,7 +316,8 @@ export class Queuer<TValue> {
|
|
|
300
316
|
}
|
|
301
317
|
|
|
302
318
|
/**
|
|
303
|
-
* Resets the queuer to its initial state
|
|
319
|
+
* Resets the queuer to its initial state. Optionally repopulates with initial items.
|
|
320
|
+
* Does not affect callbacks or options.
|
|
304
321
|
*/
|
|
305
322
|
reset(withInitialItems?: boolean): void {
|
|
306
323
|
this.clear()
|
|
@@ -312,8 +329,16 @@ export class Queuer<TValue> {
|
|
|
312
329
|
}
|
|
313
330
|
|
|
314
331
|
/**
|
|
315
|
-
* Adds an item to the
|
|
316
|
-
*
|
|
332
|
+
* Adds an item to the queue. If the queue is full, the item is rejected and onReject is called.
|
|
333
|
+
* Items can be inserted based on priority or at the front/back depending on configuration.
|
|
334
|
+
*
|
|
335
|
+
* Returns true if the item was added, false if the queue is full.
|
|
336
|
+
*
|
|
337
|
+
* Example usage:
|
|
338
|
+
* ```ts
|
|
339
|
+
* queuer.addItem('task');
|
|
340
|
+
* queuer.addItem('task2', 'front');
|
|
341
|
+
* ```
|
|
317
342
|
*/
|
|
318
343
|
addItem(
|
|
319
344
|
item: TValue,
|
|
@@ -330,7 +355,7 @@ export class Queuer<TValue> {
|
|
|
330
355
|
// If custom priority function is provided, insert based on priority
|
|
331
356
|
const priority = this._options.getPriority(item)
|
|
332
357
|
const insertIndex = this._items.findIndex(
|
|
333
|
-
(existing) => this._options.getPriority(existing)
|
|
358
|
+
(existing) => this._options.getPriority(existing) < priority,
|
|
334
359
|
)
|
|
335
360
|
|
|
336
361
|
if (insertIndex === -1) {
|
|
@@ -362,14 +387,15 @@ export class Queuer<TValue> {
|
|
|
362
387
|
}
|
|
363
388
|
|
|
364
389
|
/**
|
|
365
|
-
* Removes and returns
|
|
390
|
+
* Removes and returns the next item from the queue without executing the function.
|
|
391
|
+
* Use for manual queue management. Normally, use execute() to process items.
|
|
366
392
|
*
|
|
367
|
-
*
|
|
393
|
+
* Example usage:
|
|
368
394
|
* ```ts
|
|
369
|
-
* //
|
|
370
|
-
* queuer.getNextItem()
|
|
371
|
-
* //
|
|
372
|
-
* queuer.getNextItem('back')
|
|
395
|
+
* // FIFO
|
|
396
|
+
* queuer.getNextItem();
|
|
397
|
+
* // LIFO
|
|
398
|
+
* queuer.getNextItem('back');
|
|
373
399
|
* ```
|
|
374
400
|
*/
|
|
375
401
|
getNextItem(
|
|
@@ -386,22 +412,39 @@ export class Queuer<TValue> {
|
|
|
386
412
|
}
|
|
387
413
|
|
|
388
414
|
if (item !== undefined) {
|
|
389
|
-
this._executionCount++
|
|
390
415
|
this._options.onItemsChange(this)
|
|
391
|
-
this._options.onGetNextItem(item, this)
|
|
392
416
|
}
|
|
417
|
+
|
|
393
418
|
return item
|
|
394
419
|
}
|
|
395
420
|
|
|
396
421
|
/**
|
|
397
|
-
*
|
|
422
|
+
* Removes and returns the next item from the queue and processes it using the provided function.
|
|
398
423
|
*
|
|
399
|
-
*
|
|
424
|
+
* Example usage:
|
|
400
425
|
* ```ts
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
426
|
+
* queuer.execute();
|
|
427
|
+
* // LIFO
|
|
428
|
+
* queuer.execute('back');
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
execute(position?: QueuePosition): TValue | undefined {
|
|
432
|
+
const item = this.getNextItem(position)
|
|
433
|
+
if (item !== undefined) {
|
|
434
|
+
this.fn(item)
|
|
435
|
+
this._executionCount++
|
|
436
|
+
this._options.onExecute(item, this)
|
|
437
|
+
}
|
|
438
|
+
return item
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Returns the next item in the queue without removing it.
|
|
443
|
+
*
|
|
444
|
+
* Example usage:
|
|
445
|
+
* ```ts
|
|
446
|
+
* queuer.getPeek(); // front
|
|
447
|
+
* queuer.getPeek('back'); // back
|
|
405
448
|
* ```
|
|
406
449
|
*/
|
|
407
450
|
getPeek(
|
|
@@ -414,63 +457,63 @@ export class Queuer<TValue> {
|
|
|
414
457
|
}
|
|
415
458
|
|
|
416
459
|
/**
|
|
417
|
-
* Returns true if the
|
|
460
|
+
* Returns true if the queue is empty (no pending items).
|
|
418
461
|
*/
|
|
419
462
|
getIsEmpty(): boolean {
|
|
420
463
|
return this._items.length === 0
|
|
421
464
|
}
|
|
422
465
|
|
|
423
466
|
/**
|
|
424
|
-
* Returns true if the
|
|
467
|
+
* Returns true if the queue is full (reached maxSize).
|
|
425
468
|
*/
|
|
426
469
|
getIsFull(): boolean {
|
|
427
470
|
return this._items.length >= this._options.maxSize
|
|
428
471
|
}
|
|
429
472
|
|
|
430
473
|
/**
|
|
431
|
-
* Returns the
|
|
474
|
+
* Returns the number of pending items in the queue.
|
|
432
475
|
*/
|
|
433
476
|
getSize(): number {
|
|
434
477
|
return this._items.length
|
|
435
478
|
}
|
|
436
479
|
|
|
437
480
|
/**
|
|
438
|
-
* Returns a copy of all items in the
|
|
481
|
+
* Returns a copy of all items in the queue.
|
|
439
482
|
*/
|
|
440
483
|
getAllItems(): Array<TValue> {
|
|
441
484
|
return [...this._items]
|
|
442
485
|
}
|
|
443
486
|
|
|
444
487
|
/**
|
|
445
|
-
* Returns the number of items that have been removed from the
|
|
488
|
+
* Returns the number of items that have been processed and removed from the queue.
|
|
446
489
|
*/
|
|
447
490
|
getExecutionCount(): number {
|
|
448
491
|
return this._executionCount
|
|
449
492
|
}
|
|
450
493
|
|
|
451
494
|
/**
|
|
452
|
-
* Returns the number of items that have been rejected from the
|
|
495
|
+
* Returns the number of items that have been rejected from being added to the queue.
|
|
453
496
|
*/
|
|
454
497
|
getRejectionCount(): number {
|
|
455
498
|
return this._rejectionCount
|
|
456
499
|
}
|
|
457
500
|
|
|
458
501
|
/**
|
|
459
|
-
* Returns the number of items that have expired from the
|
|
502
|
+
* Returns the number of items that have expired and been removed from the queue.
|
|
460
503
|
*/
|
|
461
504
|
getExpirationCount(): number {
|
|
462
505
|
return this._expirationCount
|
|
463
506
|
}
|
|
464
507
|
|
|
465
508
|
/**
|
|
466
|
-
* Returns true if the queuer is running
|
|
509
|
+
* Returns true if the queuer is currently running (processing items).
|
|
467
510
|
*/
|
|
468
511
|
getIsRunning() {
|
|
469
512
|
return this._running
|
|
470
513
|
}
|
|
471
514
|
|
|
472
515
|
/**
|
|
473
|
-
* Returns true if the queuer is running but has no items to process
|
|
516
|
+
* Returns true if the queuer is running but has no items to process.
|
|
474
517
|
*/
|
|
475
518
|
getIsIdle() {
|
|
476
519
|
return this._running && this.getIsEmpty()
|
|
@@ -478,34 +521,35 @@ export class Queuer<TValue> {
|
|
|
478
521
|
}
|
|
479
522
|
|
|
480
523
|
/**
|
|
481
|
-
* Creates a queue that processes items
|
|
524
|
+
* Creates a queue that processes items immediately upon addition.
|
|
482
525
|
* Items are processed sequentially in FIFO order by default.
|
|
483
526
|
*
|
|
484
527
|
* This is a simplified wrapper around the Queuer class that only exposes the
|
|
485
|
-
* `addItem` method.
|
|
486
|
-
* For more control over
|
|
487
|
-
* directly which provides methods like `start`, `stop`, `reset`, and more.
|
|
528
|
+
* `addItem` method. The queue is always running and will process items as they are added.
|
|
529
|
+
* For more control over queue processing, use the Queuer class directly.
|
|
488
530
|
*
|
|
489
|
-
*
|
|
531
|
+
* Example usage:
|
|
490
532
|
* ```ts
|
|
491
533
|
* // Basic sequential processing
|
|
492
|
-
* const processItems =
|
|
534
|
+
* const processItems = queue<number>((n) => console.log(n), {
|
|
493
535
|
* wait: 1000,
|
|
494
536
|
* onItemsChange: (queuer) => console.log(queuer.getAllItems())
|
|
495
|
-
* })
|
|
496
|
-
* processItems(1) // Logs: 1
|
|
497
|
-
* processItems(2) // Logs: 2 after 1 completes
|
|
537
|
+
* });
|
|
538
|
+
* processItems(1); // Logs: 1
|
|
539
|
+
* processItems(2); // Logs: 2 after 1 completes
|
|
498
540
|
*
|
|
499
|
-
* // Priority
|
|
500
|
-
* const processPriority =
|
|
501
|
-
* process: async (n) => console.log(n),
|
|
541
|
+
* // Priority queue
|
|
542
|
+
* const processPriority = queue<number>((n) => console.log(n), {
|
|
502
543
|
* getPriority: n => n // Higher numbers processed first
|
|
503
|
-
* })
|
|
504
|
-
* processPriority(1)
|
|
505
|
-
* processPriority(3) // Processed before 1
|
|
544
|
+
* });
|
|
545
|
+
* processPriority(1);
|
|
546
|
+
* processPriority(3); // Processed before 1
|
|
506
547
|
* ```
|
|
507
548
|
*/
|
|
508
|
-
export function queue<TValue>(
|
|
509
|
-
|
|
549
|
+
export function queue<TValue>(
|
|
550
|
+
fn: (item: TValue) => void,
|
|
551
|
+
options: QueuerOptions<TValue>,
|
|
552
|
+
) {
|
|
553
|
+
const queuer = new Queuer<TValue>(fn, options)
|
|
510
554
|
return queuer.addItem.bind(queuer)
|
|
511
555
|
}
|
package/src/rate-limiter.ts
CHANGED
|
@@ -95,7 +95,6 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
97
|
* Updates the rate limiter options
|
|
98
|
-
* Returns the new options state
|
|
99
98
|
*/
|
|
100
99
|
setOptions(newOptions: Partial<RateLimiterOptions<TFn>>): void {
|
|
101
100
|
this._options = { ...this._options, ...newOptions }
|
|
@@ -150,7 +149,7 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
150
149
|
if (this._options.windowType === 'sliding') {
|
|
151
150
|
// For sliding window, we can execute if we have capacity in the current window
|
|
152
151
|
if (this._executionTimes.length < this.getLimit()) {
|
|
153
|
-
this.
|
|
152
|
+
this.execute(...args)
|
|
154
153
|
return true
|
|
155
154
|
}
|
|
156
155
|
} else {
|
|
@@ -160,7 +159,7 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
160
159
|
const isNewWindow = oldestExecution + this.getWindow() <= now
|
|
161
160
|
|
|
162
161
|
if (isNewWindow || this._executionTimes.length < this.getLimit()) {
|
|
163
|
-
this.
|
|
162
|
+
this.execute(...args)
|
|
164
163
|
return true
|
|
165
164
|
}
|
|
166
165
|
}
|
|
@@ -169,7 +168,7 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
169
168
|
return false
|
|
170
169
|
}
|
|
171
170
|
|
|
172
|
-
private
|
|
171
|
+
private execute(...args: Parameters<TFn>): void {
|
|
173
172
|
if (!this.getEnabled()) return
|
|
174
173
|
const now = Date.now()
|
|
175
174
|
this._executionCount++
|
package/src/throttler.ts
CHANGED
|
@@ -87,7 +87,6 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Updates the throttler options
|
|
90
|
-
* Returns the new options state
|
|
91
90
|
*/
|
|
92
91
|
setOptions(newOptions: Partial<ThrottlerOptions<TFn>>): void {
|
|
93
92
|
this._options = { ...this._options, ...newOptions }
|
|
@@ -148,7 +147,7 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
148
147
|
|
|
149
148
|
// Handle leading execution
|
|
150
149
|
if (this._options.leading && timeSinceLastExecution >= wait) {
|
|
151
|
-
this.
|
|
150
|
+
this.execute(...args)
|
|
152
151
|
} else {
|
|
153
152
|
// Store the most recent arguments for potential trailing execution
|
|
154
153
|
this._lastArgs = args
|
|
@@ -161,14 +160,14 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
161
160
|
const timeoutDuration = wait - _timeSinceLastExecution
|
|
162
161
|
this._timeoutId = setTimeout(() => {
|
|
163
162
|
if (this._lastArgs !== undefined) {
|
|
164
|
-
this.
|
|
163
|
+
this.execute(...this._lastArgs)
|
|
165
164
|
}
|
|
166
165
|
}, timeoutDuration)
|
|
167
166
|
}
|
|
168
167
|
}
|
|
169
168
|
}
|
|
170
169
|
|
|
171
|
-
private
|
|
170
|
+
private execute(...args: Parameters<TFn>): void {
|
|
172
171
|
if (!this.getEnabled()) return
|
|
173
172
|
this.fn(...args) // EXECUTE!
|
|
174
173
|
this._executionCount++
|