@@ -22,18 +22,43 @@ 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+ 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+ }
2949
30- public constructor ( protected _limit ?: number ) { }
50+ function isReady ( ) : boolean {
51+ return length ( ) < limit ;
52+ }
3153
3254 /**
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.
3459 */
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 ] ;
3762 }
3863
3964 /**
@@ -46,47 +71,29 @@ export class PromiseBuffer<T> {
4671 * limit check.
4772 * @returns The original promise.
4873 */
49- public add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
50- if ( ! this . isReady ( ) ) {
74+ function add ( taskProducer : ( ) => PromiseLike < T > ) : PromiseLike < T > {
75+ if ( ! isReady ( ) ) {
5176 return SyncPromise . reject ( new SentryError ( 'Not adding Promise due to buffer limit reached.' ) ) ;
5277 }
5378
5479 // start the task and add its promise to the queue
5580 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 ) ;
5883 }
5984 void task
60- . then ( ( ) => this . remove ( task ) )
85+ . then ( ( ) => remove ( task ) )
6186 // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
6287 // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
6388 // have promises, so TS has to polyfill when down-compiling.)
6489 . then ( null , ( ) =>
65- this . remove ( task ) . then ( null , ( ) => {
90+ remove ( task ) . then ( null , ( ) => {
6691 // We have to add another catch here because `this.remove()` starts a new promise chain.
6792 } ) ,
6893 ) ;
6994 return task ;
7095 }
7196
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-
9097 /**
9198 * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
9299 *
@@ -96,7 +103,7 @@ export class PromiseBuffer<T> {
96103 * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
97104 * `false` otherwise
98105 */
99- public drain ( timeout ?: number ) : PromiseLike < boolean > {
106+ function drain ( timeout ?: number ) : PromiseLike < boolean > {
100107 return new SyncPromise < boolean > ( resolve => {
101108 // wait for `timeout` ms and then resolve to `false` (if not cancelled first)
102109 const capturedSetTimeout = setTimeout ( ( ) => {
@@ -106,10 +113,21 @@ export class PromiseBuffer<T> {
106113 } , timeout ) ;
107114
108115 // if all promises resolve in time, cancel the timer and resolve to `true`
109- void allPromises ( this . _buffer ) . then ( ( ) => {
116+ void allPromises ( buffer ) . then ( ( ) => {
110117 clearTimeout ( capturedSetTimeout ) ;
111118 resolve ( true ) ;
112119 } ) ;
113120 } ) ;
114121 }
122+
123+ const promiseBuffer : PromiseBuffer < T > = {
124+ _buffer : buffer ,
125+ length,
126+ isReady,
127+ add,
128+ remove,
129+ drain,
130+ } ;
131+
132+ return promiseBuffer ;
115133}
0 commit comments