Skip to content

Instantly share code, notes, and snippets.

@smnh
Created November 22, 2017 15:24
Show Gist options
  • Save smnh/21a7fb3eb6945736ade21f3faaf075e2 to your computer and use it in GitHub Desktop.
Save smnh/21a7fb3eb6945736ade21f3faaf075e2 to your computer and use it in GitHub Desktop.
Promise all with pool of concurrent promises
/**
* Like Promise.all(), this method resolves if all promises returned by invoking the "callback" are resolved, or rejects
* if at least one of these promises is rejected. This method ensures that only "poolSize" number of promises are
* executed at the same time. The "total" parameter specifies the number of total promises that need to be executed,
* therefore, the "callback" will be invoked "total" number of times. The "callback" is invoked with a single "index"
* parameter specifying the index of the invocation.
*
* @example
* let items = [...]
* return promiseAllPool(10, items.length, (index) => {
* // Return promise
* return processItem(items[index]);
* });
*
* @param {Number} poolSize number of concurrent promises
* @param {Number} total number of total promises, the callback will be invoked 'total' number of times
* @param {Function} callback function that must return a promise, it is executed with a single 'index' parameter
* @return {Promise}
*/
function promiseAllPool(poolSize, total, callback) {
return new Promise((resolve, reject) => {
let index = 0;
let finished = 0;
let results = [];
let hadError = false;
let error = null;
function onReject(_error) {
if (!hadError) {
hadError = true;
error = _error;
}
}
function doWork() {
if (index < total) {
let _index = index++;
return callback(_index).catch(onReject).then(result => {
results[_index] = result;
return doWork();
});
} else {
finished++;
if (finished === poolSize) {
if (hadError) {
reject(error);
} else {
resolve(results);
}
}
return null;
}
}
for (let i = 0; i < poolSize; i++) {
doWork();
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment