@momsfriendlydevco/moody
Version:
MOngoose On DYnamo - Wrapper for AWS, bringing the API closer to Mongoose
54 lines (50 loc) • 2.25 kB
JavaScript
var utils = {};
module.exports = utils;
/**
* Resolve promises similar to Promise.all() but only allow a set number of promises to be running at once
* This works the same as Promise.all() but resolves its payload until all promises are resolved
* NOTE: Because of the immediately-executing 'feature' of Promises it is recommended that the input array provide
* an array of functions which return Promises rather than promises directly - i.e. return promise factories
*
* @param {array <Function>} promises An array of promise FACTORIES which will be evaluated
* @returns {Promise} A promise which will resolve/reject based on the completion of the given promise factories being resolved
* @url https://github.com/MomsFriendlyDevCo/Nodash
*
* @example Evaluate a series of promises with a delay, one at a time, in order (note that the map returns a promise factory, otherwise the promise would execute immediately)
* Promise.allLimit(
* 3, // Allow only 3 promises to run at once
* [500, 400, 300, 200, 100, 0, 100, 200, 300, 400, 500].map((delay, index) => ()=> new Promise(resolve => {
* setTimeout(()=> { console.log('EVAL', index, delay); resolve(); }, delay);
* }))
* )
*/
utils.promiseThrottle = (limit, promises) => new Promise((resolve, reject) => {
if (!isFinite(limit)) throw new Error('First parameter must be the number of promise threads');
var promiseChecker = function(queue) {
if (!queue.promisesRemaining.length && queue.running == 0) return resolve(queue.output);
while (queue.promisesRemaining.length > 0 && queue.running < queue.limit) {
var promiseRunner = function(thisPromise, promiseIndex) {
queue.running++;
Promise.resolve(thisPromise())
.then(res => {
queue.output[promiseIndex] = res;
queue.completed++;
queue.running--;
// Potential to do some progress notification here:
// notify({completed: queue.completed, count: queue.promiseCount, limit: queue.limit});
promiseChecker(queue);
})
.catch(reject);
}(queue.promisesRemaining.shift(), queue.promiseIndex++);
}
};
promiseChecker({
limit,
running: 0,
promiseCount: promises.length,
completed: 0,
promisesRemaining: promises,
output: [],
promiseIndex: 0,
});
});