Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Last active December 3, 2019 23:06
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/a4fa05a777d063ef9203783afccd2046 to your computer and use it in GitHub Desktop.
Save XoseLluis/a4fa05a777d063ef9203783afccd2046 to your computer and use it in GitHub Desktop.
Throttiling async calls
class TicketProvider{
constructor(maxActiveTickets){
this.activeTickets = 0;
this.maxActiveTickets = maxActiveTickets;
this.waitingTickets = []; //array of resolve function, to get invoked once we have a free slot, so the code waiting for the ticket can move on
}
//returns Promise<void>
getTicket(){
if (this.activeTickets<this.maxActiveTickets){
this.activeTickets++;
return Promise.resolve();
}
else {
return new Promise(res => {
//save the resolve function so that we can invoke it when another ticket gets released
this.waitingTickets.push(res);
});
}
}
releaseTicket(){
this.activeTickets--;
let nextTicketToResolve = this.waitingTickets.shift();
if (nextTicketToResolve) {
nextTicketToResolve();
}
}
}
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)));
});
}
//returns :Promise<string>
async function getPostAndReleaseTicket(postId, ticketProvider){
let post = await getPost(postId);
ticketProvider.releaseTicket();
return post;
}
//returns :Promise<string>
async function getTicketAndGetPostAndReleaseTicket(postId, ticketProvider){
await ticketProvider.getTicket();
let post = await getPost(postId);
ticketProvider.releaseTicket();
return post;
}
async function runWithoutThrottling(){
let curPos = 0;
let requests = [];
while (curPos < 10){
requests.push(getPost(curPos));
curPos++;
}
await Promise.all(requests);
console.log("all posts retrieved");
}
async function runWithThrottling1(){
let ticketProvider = new TicketProvider(3);
let curPos = 0;
let requests = [];
while (curPos < 10){
let ticket = await ticketProvider.getTicket();
requests.push(getPostAndReleaseTicket(curPos, ticketProvider));
curPos++;
}
await Promise.all(requests);
console.log("all posts retrieved");
}
async function runWithThrottling2(){
let ticketProvider = new TicketProvider(3);
let curPos = 0;
let requests = [];
while (curPos < 10){
requests.push(getTicketAndGetPostAndReleaseTicket(curPos, ticketProvider));
curPos++;
}
await Promise.all(requests);
console.log("all posts retrieved");
}
let op = process.argv.length > 2 ? process.argv[2] : "1";
switch (op){
case "0":
runWithoutThrottling();
break;
case "1":
runWithThrottling1();
break;
case "2":
runWithThrottling2();
break;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment