Skip to content

Instantly share code, notes, and snippets.

@MikeyBurkman
Last active October 20, 2017 19:27
Show Gist options
  • Save MikeyBurkman/d1475d2fad4dd150d1fcd7d1d7f32708 to your computer and use it in GitHub Desktop.
Save MikeyBurkman/d1475d2fad4dd150d1fcd7d1d7f32708 to your computer and use it in GitHub Desktop.
Parallel each() promise implementation (since Bluebird does not have one)
'use strict';
module.exports = function each(items, fn, concurrency) {
if (items.length === 0) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
let error = false;
let currIndex = 0;
let processingCount = 0;
for (let i = 0; i < Math.min(concurrency, items.length); i += 1) {
startNewWorker();
}
function onComplete() {
processingCount -= 1;
const itemsRemaining = items.length - currIndex;
if (!error && itemsRemaining === 0 && processingCount === 0) {
resolve();
}
if (!error && itemsRemaining > 0) {
startNewWorker();
}
}
function onError(err) {
error = true;
reject(err);
}
function startNewWorker() {
processingCount += 1;
const item = items[currIndex++];
Promise.resolve()
.then(() => fn(item))
.then(onComplete, onError);
};
});
};
'use strict';
const each = require('./each');
const delay = function(n) {
return new Promise((resolve) => setTimeout(resolve, n));
};
const testData = [];
for (let i = 1; i < 51; i += 1) {
testData.push(i);
}
const task = (n) => {
const delayMs = Math.ceil(Math.random() * 400);
console.log(`Starting: ${n}: ${delayMs}ms`);
return delay(delayMs).then(() => console.log(`Finished ${n}`));
};
const start = Date.now();
each(testData, task, 4)
.then(() => console.log('Finished!'))
.catch((err) => console.log(err.stack))
.then(() => console.log(`Total time: ${Date.now() - start}`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment