@@ -22,18 +22,43 @@ function allPromises<U = unknown>(collection: Array<U | PromiseLike<U>>): Promis
22
22
} ) ;
23
23
}
24
24
25
- /** A simple queue that holds promises. */
26
- export class PromiseBuffer < T > {
27
- /** Internal set of queued Promises */
28
- private readonly _buffer : Array < PromiseLike < T > > = [ ] ;
25
+ interface PromiseBuffer < T > {
26
+ _buffer : Array < PromiseLike < T > > ;
27
+ isReady ( ) : boolean ;
28
+ add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > ;
29
+ remove ( task : PromiseLike < T > ) : PromiseLike < T > ;
30
+ length ( ) : number ;
31
+ drain ( timeout ?: number ) : PromiseLike < boolean > ;
32
+ }
33
+
34
+ const DEFAULT_BUFFER_LIMIT = 30 ;
35
+
36
+ /**
37
+ * Create a new promise buffer
38
+ * @param limit
39
+ */
40
+ export function makePromiseBuffer < T > ( limit : number = DEFAULT_BUFFER_LIMIT ) : PromiseBuffer < T > {
41
+ const buffer : Array < PromiseLike < T > > = [ ] ;
42
+
43
+ /**
44
+ * This function returns the number of unresolved promises in the queue.
45
+ */
46
+ function length ( ) : number {
47
+ return buffer . length ;
48
+ }
29
49
30
- public constructor ( protected _limit ?: number ) { }
50
+ function isReady ( ) : boolean {
51
+ return length ( ) < limit ;
52
+ }
31
53
32
54
/**
33
- * Says if the buffer is ready to take more requests
55
+ * Remove a promise from the queue.
56
+ *
57
+ * @param task Can be any PromiseLike<T>
58
+ * @returns Removed promise.
34
59
*/
35
- public isReady ( ) : boolean {
36
- return this . _limit === undefined || this . length ( ) < this . _limit ;
60
+ function remove ( task : PromiseLike < T > ) : PromiseLike < T > {
61
+ return buffer . splice ( buffer . indexOf ( task ) , 1 ) [ 0 ] ;
37
62
}
38
63
39
64
/**
@@ -46,47 +71,29 @@ export class PromiseBuffer<T> {
46
71
* limit check.
47
72
* @returns The original promise.
48
73
*/
49
- public add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
50
- if ( ! this . isReady ( ) ) {
74
+ function add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
75
+ if ( ! isReady ( ) ) {
51
76
return SyncPromise . reject ( new SentryError ( 'Not adding Promise due to buffer limit reached.' ) ) ;
52
77
}
53
78
54
79
// start the task and add its promise to the queue
55
80
const task = taskProducer ( ) ;
56
- if ( this . _buffer . indexOf ( task ) === - 1 ) {
57
- this . _buffer . push ( task ) ;
81
+ if ( buffer . indexOf ( task ) === - 1 ) {
82
+ buffer . push ( task ) ;
58
83
}
59
84
void task
60
- . then ( ( ) => this . remove ( task ) )
85
+ . then ( ( ) => remove ( task ) )
61
86
// Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
62
87
// rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
63
88
// have promises, so TS has to polyfill when down-compiling.)
64
89
. then ( null , ( ) =>
65
- this . remove ( task ) . then ( null , ( ) => {
90
+ remove ( task ) . then ( null , ( ) => {
66
91
// We have to add another catch here because `this.remove()` starts a new promise chain.
67
92
} ) ,
68
93
) ;
69
94
return task ;
70
95
}
71
96
72
- /**
73
- * Remove a promise from the queue.
74
- *
75
- * @param task Can be any PromiseLike<T>
76
- * @returns Removed promise.
77
- */
78
- public remove ( task : PromiseLike < T > ) : PromiseLike < T > {
79
- const removedTask = this . _buffer . splice ( this . _buffer . indexOf ( task ) , 1 ) [ 0 ] ;
80
- return removedTask ;
81
- }
82
-
83
- /**
84
- * This function returns the number of unresolved promises in the queue.
85
- */
86
- public length ( ) : number {
87
- return this . _buffer . length ;
88
- }
89
-
90
97
/**
91
98
* Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
92
99
*
@@ -96,7 +103,7 @@ export class PromiseBuffer<T> {
96
103
* @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
97
104
* `false` otherwise
98
105
*/
99
- public drain ( timeout ?: number ) : PromiseLike < boolean > {
106
+ function drain ( timeout ?: number ) : PromiseLike < boolean > {
100
107
return new SyncPromise < boolean > ( resolve => {
101
108
// wait for `timeout` ms and then resolve to `false` (if not cancelled first)
102
109
const capturedSetTimeout = setTimeout ( ( ) => {
@@ -106,10 +113,21 @@ export class PromiseBuffer<T> {
106
113
} , timeout ) ;
107
114
108
115
// if all promises resolve in time, cancel the timer and resolve to `true`
109
- void allPromises ( this . _buffer ) . then ( ( ) => {
116
+ void allPromises ( buffer ) . then ( ( ) => {
110
117
clearTimeout ( capturedSetTimeout ) ;
111
118
resolve ( true ) ;
112
119
} ) ;
113
120
} ) ;
114
121
}
122
+
123
+ const promiseBuffer : PromiseBuffer < T > = {
124
+ _buffer : buffer ,
125
+ length,
126
+ isReady,
127
+ add,
128
+ remove,
129
+ drain,
130
+ } ;
131
+
132
+ return promiseBuffer ;
115
133
}
0 commit comments