Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Last active December 4, 2019 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XoseLluis/125b70a582b4582d03860132d587985a to your computer and use it in GitHub Desktop.
Save XoseLluis/125b70a582b4582d03860132d587985a to your computer and use it in GitHub Desktop.
Like Promise.all, but limiting how many functions to run in parallel. https://deploytonenyures.blogspot.com/2019/12/promiseall-with-limit.html
//I'm calling "task" to a function that when executed returns a Promise
class PromiseAllWithLimit{
constructor(tasks, maxItems){
this.allTasks = tasks;
this.maxItems = maxItems;
this.taskResults = [];
this.nextTaskId = 0;
this.resolveAll = null; //points to the resolve function to invoke when all tasks are complete
this.completedCounter = 0;
}
//tasks: Array of functions that return a Promise
//returns a Promise that gets resolved when all tasks are done
run(){
while(this.nextTaskId < this.maxItems){
this._runNextTask();
}
return new Promise((res) => this.resolveAll = res);
}
_runNextTask(){
//we need this var to get it trapped in the closure to run in the task.then()
let curTaskId = this.nextTaskId
let nextTask = this.allTasks[this.nextTaskId];
this.nextTaskId++;
nextTask().then((result) => {
this.completedCounter++;
this.taskResults[curTaskId] = result;
if (this.nextTaskId < this.allTasks.length){
this._runNextTask();
}
else{
//no more tasks to launch
//if all tasks are complete, complete the All Promise
if(this.completedCounter === this.allTasks.length){
this.resolveAll(this.taskResults);
}
}
});
}
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
//returns Promise<string>
function getPost(postId){
console.log("getPost " + postId + " started");
return new Promise(res => {
setTimeout(() => {
console.log("---> getPost " + postId + " finishing");
res(`${postId} - content`)
}, 2000 * (1 + getRandomInt(2)));
});
}
(async () => {
let tasks = [];
for (let i=0; i<10; i++){
tasks.push(() => getPost("postId_" + i));
}
let results = await new PromiseAllWithLimit(tasks, 5).run();
console.log("all tasks are complete");
console.log(results.join("\n"));
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment