Repository URL to install this package:
|
Version:
3.12.2 ▾
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
/**
* Array.prototype.findIndex ponyfill for old browsers.
*/
function findIndex(array, predicate) {
for (var i = 0; i < array.length; i++) {
if (predicate(array[i])) return i;
}
return -1;
}
function createCancelError() {
return new Error('Cancelled');
}
var RateLimitedQueue = /*#__PURE__*/function () {
function RateLimitedQueue(limit) {
_classCallCheck(this, RateLimitedQueue);
if (typeof limit !== 'number' || limit === 0) {
this.limit = Infinity;
} else {
this.limit = limit;
}
this.activeRequests = 0;
// eslint-disable-next-line no-unused-expressions
this.pauseTimer;
this.queuedHandlers = [];
this.paused = false;
}
_createClass(RateLimitedQueue, [{
key: "_call",
value: function _call(fn) {
var _this = this;
this.activeRequests += 1;
var _done = false;
var cancelActive;
try {
cancelActive = fn();
} catch (err) {
this.activeRequests -= 1;
throw err;
}
return {
abort: function abort() {
if (_done) return;
_done = true;
_this.activeRequests -= 1;
cancelActive();
_this._queueNext();
},
done: function done() {
if (_done) return;
_done = true;
_this.activeRequests -= 1;
_this._queueNext();
}
};
}
}, {
key: "_queueNext",
value: function _queueNext() {
var _this2 = this;
// Do it soon but not immediately, this allows clearing out the entire queue synchronously
// one by one without continuously _advancing_ it (and starting new tasks before immediately
// aborting them)
Promise.resolve().then(function () {
_this2._next();
});
}
}, {
key: "_next",
value: function _next() {
if (this.paused || this.activeRequests >= this.limit) {
return;
}
if (this.queuedHandlers.length === 0) {
return;
}
// Dispatch the next request, and update the abort/done handlers
// so that cancelling it does the Right Thing (and doesn't just try
// to dequeue an already-running request).
var next = this.queuedHandlers.shift();
var handler = this._call(next.fn);
next.abort = handler.abort;
next.done = handler.done;
}
}, {
key: "_queue",
value: function _queue(fn) {
var _this3 = this;
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var handler = {
fn: fn,
priority: options.priority || 0,
abort: function abort() {
_this3._dequeue(handler);
},
done: function done() {
throw new Error('Cannot mark a queued request as done: this indicates a bug');
}
};
var index = findIndex(this.queuedHandlers, function (other) {
return handler.priority > other.priority;
});
if (index === -1) {
this.queuedHandlers.push(handler);
} else {
this.queuedHandlers.splice(index, 0, handler);
}
return handler;
}
}, {
key: "_dequeue",
value: function _dequeue(handler) {
var index = this.queuedHandlers.indexOf(handler);
if (index !== -1) {
this.queuedHandlers.splice(index, 1);
}
}
}, {
key: "run",
value: function run(fn, queueOptions) {
if (!this.paused && this.activeRequests < this.limit) {
return this._call(fn);
}
return this._queue(fn, queueOptions);
}
}, {
key: "wrapPromiseFunction",
value: function wrapPromiseFunction(fn, queueOptions) {
var _this4 = this;
return function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var queuedRequest;
var outerPromise = new Promise(function (resolve, reject) {
queuedRequest = _this4.run(function () {
var cancelError;
var innerPromise;
try {
innerPromise = Promise.resolve(fn.apply(void 0, args));
} catch (err) {
innerPromise = Promise.reject(err);
}
innerPromise.then(function (result) {
if (cancelError) {
reject(cancelError);
} else {
queuedRequest.done();
resolve(result);
}
}, function (err) {
if (cancelError) {
reject(cancelError);
} else {
queuedRequest.done();
reject(err);
}
});
return function () {
cancelError = createCancelError();
};
}, queueOptions);
});
outerPromise.abort = function () {
queuedRequest.abort();
};
return outerPromise;
};
}
}, {
key: "resume",
value: function resume() {
this.paused = false;
clearTimeout(this.pauseTimer);
for (var i = 0; i < this.limit; i++) {
this._queueNext();
}
}
}, {
key: "pause",
value: function pause() {
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
this.paused = true;
clearTimeout(this.pauseTimer);
if (duration != null) {
this.pauseTimer = setTimeout(this.resume, duration);
}
}
}]);
return RateLimitedQueue;
}();
export { RateLimitedQueue as default };