You can achieve it using a plugin like bluebird
which have a function allowing it : example here
const Promise = require('bluebird');
const _ = require('lodash');
let tasks = [...]; // over 10,000 items.
Promise.all(
_(tasks).map(task => {
return task.doAsyncThing();
})
.value();
);
Promise.map(
tasks,
task => {
return task.doAsyncThing();
},
{ concurrency: 1000 }
);
You can also create a function yourself that's gonna handle it. Here is one function I've made up myself, ofc it's improvable.
const resultPromises = [];
let nextToCall = 0;
let errorHappened = false;
/**
* Function that get called when one promise got executed
*/
function callbackOnePromiseGotExecuted({
error,
result,
allExecutedCallback,
array,
}) {
resultPromises.push(result);
// Do nothing if an error got reported
if (errorHappened) {
return;
}
// Return the error
if (error) {
allExecutedCallback(null, resultPromises);
errorHappened = true;
return;
}
// Check if it was the last promise to execute
if (resultPromises.length === array.length) {
allExecutedCallback(null, resultPromises);
return;
}
nextToCall += 1;
// Stop if we already acalled everything
if (nextToCall > array.length) return;
// If it wasn't call a new promise
array[nextToCall - 1].call()
.then(ret => callbackOnePromiseGotExecuted({
error: null,
result: ret,
allExecutedCallback,
array,
}))
.catch(e => callbackOnePromiseGotExecuted({
error: e,
result: null,
allExecutedCallback,
array,
}));
}
/**
* Handle the call of multiple promise with concurrency
*/
function promiseWithConcurrencyCallback({
array,
concurrencyNumber,
allExecutedCallback,
}) {
for (let i = 0; i < concurrencyNumber; ++i) {
array[nextToCall].call()
.then(ret => callbackOnePromiseGotExecuted({
error: null,
result: ret,
allExecutedCallback,
array,
}))
.catch(e => callbackOnePromiseGotExecuted({
error: e,
result: null,
allExecutedCallback,
array,
}));
nextToCall += 1;
}
}
function promiseWithConcurrency(array, concurrencyNumber) {
return new Promise((resolve, reject) => {
promiseWithConcurrencyCallback({
array,
concurrencyNumber,
allExecutedCallback: (error, result) => {
if (error) return reject(error);
return resolve(result);
},
});
});
}
const array = [
() => new Promise((resolve) => resolve('01')),
() => new Promise((resolve) => resolve('02')),
() => new Promise((resolve) => resolve('03')),
() => new Promise((resolve) => resolve('04')),
() => new Promise((resolve) => resolve('05')),
() => new Promise((resolve) => resolve('06')),
];
promiseWithConcurrency(array, 2)
.then(rets => console.log('rets', rets))
.catch(error => console.log('error', error));
EDIT about my comment on @Redu post
var ps = [new Promise((resolve) => { console.log('A'); setTimeout(() => { resolve(1) }, 5000); }), Promise.resolve(2), Promise.resolve(3), Promise.resolve(4), new Promise((resolve) => { console.log('B'); setTimeout(() => { resolve(5) }, 5000); })],
groupBy = (n,a) => a.reduce((r,p,i) => !(i%n) ? (r.push([p]),r) : (r[r.length-1].push(p),r),[]);
groupBy(2,ps).map(sps => Promise.all(sps).then(console.log));
As you can see in the snippet you gave I've edited, console.log('A')
and console.log('B')
are showed right away. It means that the functions are executed at the same time and then resolved two per two. So if the purpose is to limitate the access to a ressource or something, your soluce won't work. They will still all access on the same time.