@@ -4,26 +4,23 @@ import {Queue, RunFunction} from './queue.js';
4
4
import PriorityQueue from './priority-queue.js' ;
5
5
import { QueueAddOptions , Options , TaskOptions } from './options.js' ;
6
6
7
- type ResolveFunction < T = void > = ( value ?: T | PromiseLike < T > ) => void ;
8
-
9
7
type Task < TaskResultType > =
10
8
| ( ( options : TaskOptions ) => PromiseLike < TaskResultType > )
11
9
| ( ( options : TaskOptions ) => TaskResultType ) ;
12
10
13
- // eslint-disable-next-line @typescript-eslint/no-empty-function
14
- const empty = ( ) : void => { } ;
15
-
16
11
const timeoutError = new TimeoutError ( ) ;
17
12
18
13
/**
19
14
The error thrown by `queue.add()` when a job is aborted before it is run. See `signal`.
20
15
*/
21
16
export class AbortError extends Error { }
22
17
18
+ type EventName = 'active' | 'idle' | 'empty' | 'add' | 'next' | 'completed' | 'error' ;
19
+
23
20
/**
24
21
Promise queue with concurrency control.
25
22
*/
26
- export default class PQueue < QueueType extends Queue < RunFunction , EnqueueOptionsType > = PriorityQueue , EnqueueOptionsType extends QueueAddOptions = QueueAddOptions > extends EventEmitter < 'active' | 'idle' | 'add' | 'next' | 'completed' | 'error' > {
23
+ export default class PQueue < QueueType extends Queue < RunFunction , EnqueueOptionsType > = PriorityQueue , EnqueueOptionsType extends QueueAddOptions = QueueAddOptions > extends EventEmitter < EventName > {
27
24
readonly #carryoverConcurrencyCount: boolean ;
28
25
29
26
readonly #isIntervalIgnored: boolean ;
@@ -51,13 +48,14 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
51
48
52
49
#isPaused: boolean ;
53
50
54
- #resolveEmpty: ResolveFunction = empty ;
55
-
56
- #resolveIdle: ResolveFunction = empty ;
51
+ readonly #throwOnTimeout: boolean ;
57
52
58
- #timeout?: number ;
53
+ /**
54
+ Per-operation timeout in milliseconds. Operations fulfill once `timeout` elapses if they haven't already.
59
55
60
- readonly #throwOnTimeout: boolean ;
56
+ Applies to each future operation.
57
+ */
58
+ timeout ?: number ;
61
59
62
60
constructor ( options ?: Options < QueueType , EnqueueOptionsType > ) {
63
61
super ( ) ;
@@ -88,7 +86,7 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
88
86
this . #queue = new options . queueClass ! ( ) ;
89
87
this . #queueClass = options . queueClass ! ;
90
88
this . concurrency = options . concurrency ! ;
91
- this . # timeout = options . timeout ;
89
+ this . timeout = options . timeout ;
92
90
this . #throwOnTimeout = options . throwOnTimeout === true ;
93
91
this . #isPaused = options . autoStart === false ;
94
92
}
@@ -107,13 +105,10 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
107
105
this . emit ( 'next' ) ;
108
106
}
109
107
110
- #resolvePromises( ) : void {
111
- this . #resolveEmpty( ) ;
112
- this . #resolveEmpty = empty ;
108
+ #emitEvents( ) : void {
109
+ this . emit ( 'empty' ) ;
113
110
114
111
if ( this . #pendingCount === 0 ) {
115
- this . #resolveIdle( ) ;
116
- this . #resolveIdle = empty ;
117
112
this . emit ( 'idle' ) ;
118
113
}
119
114
}
@@ -124,7 +119,7 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
124
119
this . #timeoutId = undefined ;
125
120
}
126
121
127
- #isIntervalPaused( ) : boolean {
122
+ get #isIntervalPaused( ) : boolean {
128
123
const now = Date . now ( ) ;
129
124
130
125
if ( this . #intervalId === undefined ) {
@@ -161,13 +156,13 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
161
156
162
157
this . #intervalId = undefined ;
163
158
164
- this . #resolvePromises ( ) ;
159
+ this . #emitEvents ( ) ;
165
160
166
161
return false ;
167
162
}
168
163
169
164
if ( ! this . #isPaused) {
170
- const canInitializeInterval = ! this . #isIntervalPaused( ) ;
165
+ const canInitializeInterval = ! this . #isIntervalPaused;
171
166
if ( this . #doesIntervalAllowAnother && this . #doesConcurrentAllowAnother) {
172
167
const job = this . #queue. dequeue ( ) ;
173
168
if ( ! job ) {
@@ -251,9 +246,9 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
251
246
return ;
252
247
}
253
248
254
- const operation = ( this . # timeout === undefined && options . timeout === undefined ) ? fn ( { signal : options . signal } ) : pTimeout (
249
+ const operation = ( this . timeout === undefined && options . timeout === undefined ) ? fn ( { signal : options . signal } ) : pTimeout (
255
250
Promise . resolve ( fn ( { signal : options . signal } ) ) ,
256
- ( options . timeout === undefined ? this . # timeout : options . timeout ) ! ,
251
+ ( options . timeout === undefined ? this . timeout : options . timeout ) ! ,
257
252
( ) => {
258
253
if ( options . throwOnTimeout === undefined ? this . #throwOnTimeout : options . throwOnTimeout ) {
259
254
reject ( timeoutError ) ;
@@ -331,13 +326,7 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
331
326
return ;
332
327
}
333
328
334
- return new Promise < void > ( resolve => {
335
- const existingResolve = this . #resolveEmpty;
336
- this . #resolveEmpty = ( ) => {
337
- existingResolve ( ) ;
338
- resolve ( ) ;
339
- } ;
340
- } ) ;
329
+ await this . #onEvent( 'empty' ) ;
341
330
}
342
331
343
332
/**
@@ -353,16 +342,7 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
353
342
return ;
354
343
}
355
344
356
- return new Promise < void > ( resolve => {
357
- const listener = ( ) => {
358
- if ( this . #queue. size < limit ) {
359
- this . removeListener ( 'next' , listener ) ;
360
- resolve ( ) ;
361
- }
362
- } ;
363
-
364
- this . on ( 'next' , listener ) ;
365
- } ) ;
345
+ await this . #onEvent( 'next' , ( ) => this . #queue. size < limit ) ;
366
346
}
367
347
368
348
/**
@@ -376,12 +356,21 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
376
356
return ;
377
357
}
378
358
379
- return new Promise < void > ( resolve => {
380
- const existingResolve = this . #resolveIdle;
381
- this . #resolveIdle = ( ) => {
382
- existingResolve ( ) ;
359
+ await this . #onEvent( 'idle' ) ;
360
+ }
361
+
362
+ async #onEvent( event : EventName , filter ?: ( ) => boolean ) : Promise < void > {
363
+ return new Promise ( resolve => {
364
+ const listener = ( ) => {
365
+ if ( filter && ! filter ( ) ) {
366
+ return ;
367
+ }
368
+
369
+ this . off ( event , listener ) ;
383
370
resolve ( ) ;
384
371
} ;
372
+
373
+ this . on ( event , listener ) ;
385
374
} ) ;
386
375
}
387
376
@@ -415,17 +404,6 @@ export default class PQueue<QueueType extends Queue<RunFunction, EnqueueOptionsT
415
404
get isPaused ( ) : boolean {
416
405
return this . #isPaused;
417
406
}
418
-
419
- get timeout ( ) : number | undefined {
420
- return this . #timeout;
421
- }
422
-
423
- /**
424
- Set the timeout for future operations.
425
- */
426
- set timeout ( milliseconds : number | undefined ) {
427
- this . #timeout = milliseconds ;
428
- }
429
407
}
430
408
431
409
// TODO: Rename `DefaultAddOptions` to `QueueAddOptions` in next major version
0 commit comments