@image/packer
Version:
image packer
111 lines (110 loc) • 3.5 kB
JavaScript
var resolveWith = function (value) {
if (value && typeof value.then === 'function') {
return value;
}
return new Promise(function (resolve) {
resolve(value);
});
};
/**
* It limits concurrently executed promises
* @example
*
* var queue = new Queue(1);
*
* queue.add(function () {
* // resolve of this promise will resume next request
* return downloadTarballFromGithub(url, file);
* })
* .then(function (file) {
* doStuffWith(file);
* });
*
* queue.add(function () {
* return downloadTarballFromGithub(url, file);
* })
* // This request will be paused
* .then(function (file) {
* doStuffWith(file);
* });
*/
var PromiseQueue = (function () {
/**
* @param [maxPendingPromises=Infinity] max number of concurrently executed promises
* @param [maxQueuedPromises=Infinity] max number of queued promises
*/
function PromiseQueue(maxPendingPromises, maxQueuedPromises) {
this.pendingPromises = 0;
this.maxPendingPromises = typeof maxPendingPromises !== 'undefined' ? maxPendingPromises : Infinity;
this.maxQueuedPromises = typeof maxQueuedPromises !== 'undefined' ? maxQueuedPromises : Infinity;
this.queue = [];
}
PromiseQueue.prototype.add = function (promiseGenerator) {
var self = this;
return new Promise(function (resolve, reject) {
// Do not queue to much promises
if (self.queue.length >= self.maxQueuedPromises) {
reject(new Error('Queue limit reached'));
return;
}
// Add to queue
self.queue.push({
promiseGenerator: promiseGenerator,
resolve: resolve,
reject: reject
});
self._dequeue();
});
};
/**
* Number of simultaneously running promises (which are resolving)
*/
PromiseQueue.prototype.getPendingLength = function () {
return this.pendingPromises;
};
/**
* Number of queued promises (which are waiting)
*/
PromiseQueue.prototype.getQueueLength = function () {
return this.queue.length;
};
/**
* @returns true if first item removed from queue
*/
PromiseQueue.prototype._dequeue = function () {
var self = this;
if (this.pendingPromises >= this.maxPendingPromises) {
return false;
}
// Remove from queue
var item = this.queue.shift();
if (!item) {
return false;
}
try {
this.pendingPromises++;
resolveWith(item.promiseGenerator())
.then(function (value) {
// It is not pending now
self.pendingPromises--;
// It should pass values
item.resolve(value);
self._dequeue();
}, function (err) {
// It is not pending now
self.pendingPromises--;
// It should not mask errors
item.reject(err);
self._dequeue();
});
}
catch (err) {
self.pendingPromises--;
item.reject(err);
self._dequeue();
}
return true;
};
return PromiseQueue;
}());
export default PromiseQueue;