Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Created August 19, 2022 10:33
Show Gist options
  • Save XoseLluis/e4dba810ed2fb7ac88f03724142dd244 to your computer and use it in GitHub Desktop.
Save XoseLluis/e4dba810ed2fb7ac88f03724142dd244 to your computer and use it in GitHub Desktop.
asyncExecutor to limit the number of javascript async calls running at a given time
class AsyncAction{
constructor(fn, args, resolveFn, rejectFn){
this.fn = fn;
this.args = args;
this.resolveFn = resolveFn;
this.rejectFn = rejectFn;
}
}
export class AsyncExecutor{
constructor(maxRunningActions){
this.maxRunningActions = maxRunningActions;
this.runningCounter = 0;
this.pendingActions = [];
}
submit(fn, ...args){
let resolveFn, rejectFn;
let pr = new Promise((resFn, rejFn) => {
resolveFn = resFn;
rejectFn = rejFn;
});
let action = new AsyncAction(fn, args, resolveFn, rejectFn);
if (this.runningCounter < this.maxRunningActions){
this._runAction(action);
}
else{
this.pendingActions.push(action);
}
return pr;
}
async _runAction(action){
this.runningCounter++;
let result;
try{
result = await action.fn(...(action.args));
}
catch (ex){
this._processActionResult(action, false, ex);
return;
}
this._processActionResult(action, true, result);
}
_processActionResult(action, successful /*bool*/, result){
this.runningCounter--;
if (successful){
action.resolveFn(result);
}
else{
action.rejectFn(result); //here result is an exception
}
if (this.pendingActions.length){
this.runningCounter++;
this._runAction(this.pendingActions.shift());
}
}
}
import {AsyncExecutor} from "./asyncExecutor.js"
function asyncSleep(interval){
return new Promise(resFn => {
setTimeout(resFn, interval);
})
}
async function mockDownload(url, delay){
console.log(`starting download: ${url}`);
await asyncSleep(delay);
return url.toUpperCase();
}
let executor = new AsyncExecutor(3);
let asyncDownloads = []
for (let i=0; i<= 6; i++){
asyncDownloads.push(executor.submit(
mockDownload,
`www.jesoutienslapolice.fr/post_${i}`, Math.floor(Math.random() * 4000)
).then(result => {
console.log(`download ${i} finished`);
return result;
}));
console.log("after submit");
}
let results = await Promise.all(asyncDownloads);
console.log(`results: ${JSON.stringify(results, null, "\t")}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment