Last active
December 4, 2019 21:46
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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