@@ -22,18 +22,41 @@ function allPromises<U = unknown>(collection: Array<U | PromiseLike<U>>): Promis
2222 } ) ;
2323}
2424
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+ export 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+ /**
35+ * Creates an new PromiseBuffer object with the specified limit
36+ * @param limit max number of promises that can be stored in the buffer
37+ */
38+ export function makePromiseBuffer < T > ( limit ?: number ) : PromiseBuffer < T > {
39+ const buffer : Array < PromiseLike < T > > = [ ] ;
40+
41+ /**
42+ * This function returns the number of unresolved promises in the queue.
43+ */
44+ function length ( ) : number {
45+ return buffer . length ;
46+ }
2947
30- public constructor ( protected _limit ?: number ) { }
48+ function isReady ( ) : boolean {
49+ return limit === undefined || length ( ) < limit ;
50+ }
3151
3252 /**
33- * Says if the buffer is ready to take more requests
53+ * Remove a promise from the queue.
54+ *
55+ * @param task Can be any PromiseLike<T>
56+ * @returns Removed promise.
3457 */
35- public isReady ( ) : boolean {
36- return this . _limit === undefined || this . length ( ) < this . _limit ;
58+ function remove ( task : PromiseLike < T > ) : PromiseLike < T > {
59+ return buffer . splice ( buffer . indexOf ( task ) , 1 ) [ 0 ] ;
3760 }
3861
3962 /**
@@ -46,47 +69,29 @@ export class PromiseBuffer<T> {
4669 * limit check.
4770 * @returns The original promise.
4871 */
49- public add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
50- if ( ! this . isReady ( ) ) {
72+ function add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
73+ if ( ! isReady ( ) ) {
5174 return SyncPromise . reject ( new SentryError ( 'Not adding Promise due to buffer limit reached.' ) ) ;
5275 }
5376
5477 // start the task and add its promise to the queue
5578 const task = taskProducer ( ) ;
56- if ( this . _buffer . indexOf ( task ) === - 1 ) {
57- this . _buffer . push ( task ) ;
79+ if ( buffer . indexOf ( task ) === - 1 ) {
80+ buffer . push ( task ) ;
5881 }
5982 void task
60- . then ( ( ) => this . remove ( task ) )
83+ . then ( ( ) => remove ( task ) )
6184 // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
6285 // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
6386 // have promises, so TS has to polyfill when down-compiling.)
6487 . then ( null , ( ) =>
65- this . remove ( task ) . then ( null , ( ) => {
66- // We have to add another catch here because `this. remove()` starts a new promise chain.
88+ remove ( task ) . then ( null , ( ) => {
89+ // We have to add another catch here because `remove()` starts a new promise chain.
6790 } ) ,
6891 ) ;
6992 return task ;
7093 }
7194
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-
9095 /**
9196 * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
9297 *
@@ -96,7 +101,7 @@ export class PromiseBuffer<T> {
96101 * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
97102 * `false` otherwise
98103 */
99- public drain ( timeout ?: number ) : PromiseLike < boolean > {
104+ function drain ( timeout ?: number ) : PromiseLike < boolean > {
100105 return new SyncPromise < boolean > ( resolve => {
101106 // wait for `timeout` ms and then resolve to `false` (if not cancelled first)
102107 const capturedSetTimeout = setTimeout ( ( ) => {
@@ -106,10 +111,21 @@ export class PromiseBuffer<T> {
106111 } , timeout ) ;
107112
108113 // if all promises resolve in time, cancel the timer and resolve to `true`
109- void allPromises ( this . _buffer ) . then ( ( ) => {
114+ void allPromises ( buffer ) . then ( ( ) => {
110115 clearTimeout ( capturedSetTimeout ) ;
111116 resolve ( true ) ;
112117 } ) ;
113118 } ) ;
114119 }
120+
121+ const promiseBuffer : PromiseBuffer < T > = {
122+ _buffer : buffer ,
123+ length,
124+ isReady,
125+ add,
126+ remove,
127+ drain,
128+ } ;
129+
130+ return promiseBuffer ;
115131}
0 commit comments