UNPKG

4.32 kBJavaScriptView Raw
1Object.defineProperty(exports, "__esModule", { value: true });
2var error_1 = require("./error");
3var syncpromise_1 = require("./syncpromise");
4/** A simple queue that holds promises. */
5var PromiseBuffer = /** @class */ (function () {
6 function PromiseBuffer(_limit) {
7 this._limit = _limit;
8 /** Internal set of queued Promises */
9 this._buffer = [];
10 }
11 /**
12 * Says if the buffer is ready to take more requests
13 */
14 PromiseBuffer.prototype.isReady = function () {
15 return this._limit === undefined || this.length() < this._limit;
16 };
17 /**
18 * Add a promise (representing an in-flight action) to the queue, and set it to remove itself on fulfillment.
19 *
20 * @param taskProducer A function producing any PromiseLike<T>; In previous versions this used to be `task:
21 * PromiseLike<T>`, but under that model, Promises were instantly created on the call-site and their executor
22 * functions therefore ran immediately. Thus, even if the buffer was full, the action still happened. By
23 * requiring the promise to be wrapped in a function, we can defer promise creation until after the buffer
24 * limit check.
25 * @returns The original promise.
26 */
27 PromiseBuffer.prototype.add = function (taskProducer) {
28 var _this = this;
29 if (!this.isReady()) {
30 return syncpromise_1.SyncPromise.reject(new error_1.SentryError('Not adding Promise due to buffer limit reached.'));
31 }
32 // start the task and add its promise to the queue
33 var task = taskProducer();
34 if (this._buffer.indexOf(task) === -1) {
35 this._buffer.push(task);
36 }
37 void task
38 .then(function () { return _this.remove(task); })
39 // Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
40 // rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
41 // have promises, so TS has to polyfill when down-compiling.)
42 .then(null, function () {
43 return _this.remove(task).then(null, function () {
44 // We have to add another catch here because `this.remove()` starts a new promise chain.
45 });
46 });
47 return task;
48 };
49 /**
50 * Remove a promise from the queue.
51 *
52 * @param task Can be any PromiseLike<T>
53 * @returns Removed promise.
54 */
55 PromiseBuffer.prototype.remove = function (task) {
56 var removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
57 return removedTask;
58 };
59 /**
60 * This function returns the number of unresolved promises in the queue.
61 */
62 PromiseBuffer.prototype.length = function () {
63 return this._buffer.length;
64 };
65 /**
66 * Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
67 *
68 * @param timeout The time, in ms, after which to resolve to `false` if the queue is still non-empty. Passing `0` (or
69 * not passing anything) will make the promise wait as long as it takes for the queue to drain before resolving to
70 * `true`.
71 * @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
72 * `false` otherwise
73 */
74 PromiseBuffer.prototype.drain = function (timeout) {
75 var _this = this;
76 return new syncpromise_1.SyncPromise(function (resolve) {
77 // wait for `timeout` ms and then resolve to `false` (if not cancelled first)
78 var capturedSetTimeout = setTimeout(function () {
79 if (timeout && timeout > 0) {
80 resolve(false);
81 }
82 }, timeout);
83 // if all promises resolve in time, cancel the timer and resolve to `true`
84 void syncpromise_1.SyncPromise.all(_this._buffer)
85 .then(function () {
86 clearTimeout(capturedSetTimeout);
87 resolve(true);
88 })
89 .then(null, function () {
90 resolve(true);
91 });
92 });
93 };
94 return PromiseBuffer;
95}());
96exports.PromiseBuffer = PromiseBuffer;
97//# sourceMappingURL=promisebuffer.js.map
\No newline at end of file