123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- Object.defineProperty(exports, '__esModule', { value: true });
- const error = require('./error.js');
- const syncpromise = require('./syncpromise.js');
- /**
- * Creates an new PromiseBuffer object with the specified limit
- * @param limit max number of promises that can be stored in the buffer
- */
- function makePromiseBuffer(limit) {
- const buffer = [];
- function isReady() {
- return limit === undefined || buffer.length < limit;
- }
- /**
- * Remove a promise from the queue.
- *
- * @param task Can be any PromiseLike<T>
- * @returns Removed promise.
- */
- function remove(task) {
- return buffer.splice(buffer.indexOf(task), 1)[0];
- }
- /**
- * Add a promise (representing an in-flight action) to the queue, and set it to remove itself on fulfillment.
- *
- * @param taskProducer A function producing any PromiseLike<T>; In previous versions this used to be `task:
- * PromiseLike<T>`, but under that model, Promises were instantly created on the call-site and their executor
- * functions therefore ran immediately. Thus, even if the buffer was full, the action still happened. By
- * requiring the promise to be wrapped in a function, we can defer promise creation until after the buffer
- * limit check.
- * @returns The original promise.
- */
- function add(taskProducer) {
- if (!isReady()) {
- return syncpromise.rejectedSyncPromise(new error.SentryError('Not adding Promise because buffer limit was reached.'));
- }
- // start the task and add its promise to the queue
- const task = taskProducer();
- if (buffer.indexOf(task) === -1) {
- buffer.push(task);
- }
- void task
- .then(() => remove(task))
- // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
- // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
- // have promises, so TS has to polyfill when down-compiling.)
- .then(null, () =>
- remove(task).then(null, () => {
- // We have to add another catch here because `remove()` starts a new promise chain.
- }),
- );
- return task;
- }
- /**
- * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
- *
- * @param timeout The time, in ms, after which to resolve to `false` if the queue is still non-empty. Passing `0` (or
- * not passing anything) will make the promise wait as long as it takes for the queue to drain before resolving to
- * `true`.
- * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
- * `false` otherwise
- */
- function drain(timeout) {
- return new syncpromise.SyncPromise((resolve, reject) => {
- let counter = buffer.length;
- if (!counter) {
- return resolve(true);
- }
- // wait for `timeout` ms and then resolve to `false` (if not cancelled first)
- const capturedSetTimeout = setTimeout(() => {
- if (timeout && timeout > 0) {
- resolve(false);
- }
- }, timeout);
- // if all promises resolve in time, cancel the timer and resolve to `true`
- buffer.forEach(item => {
- void syncpromise.resolvedSyncPromise(item).then(() => {
- if (!--counter) {
- clearTimeout(capturedSetTimeout);
- resolve(true);
- }
- }, reject);
- });
- });
- }
- return {
- $: buffer,
- add,
- drain,
- };
- }
- exports.makePromiseBuffer = makePromiseBuffer;
- //# sourceMappingURL=promisebuffer.js.map
|