Skip to content

Instantly share code, notes, and snippets.

@distums
Created March 14, 2024 11:56
Show Gist options
  • Save distums/146021488da06a9f81446eb3fad0f0ef to your computer and use it in GitHub Desktop.
Save distums/146021488da06a9f81446eb3fad0f0ef to your computer and use it in GitHub Desktop.
asyncTask
const DEFAULT_TASK_LIMIT = 1;
type Task = () => Promise<unknown>;
enum AsyncTaskEvent {
ADD = 'task:add',
DONE = 'task:done',
IDLE = 'idle',
}
class AsyncTask extends EventTarget {
private limit: number = DEFAULT_TASK_LIMIT;
private taskQueue: [Task, Function, Function][] = [];
private runningTaskCount: number = 0;
constructor(options?: { limit?: number }) {
super();
if (Number.isInteger(options?.limit)) {
this.limit = Math.max(options!.limit!, DEFAULT_TASK_LIMIT);
}
this.addEventListener(AsyncTaskEvent.ADD, this.onTaskAdd);
this.addEventListener(AsyncTaskEvent.DONE, this.onTaskDone);
}
onTaskAdd = () => {
if (this.runningTaskCount < this.limit) {
this.runTask();
}
};
onTaskDone = () => {
if (this.taskQueue.length > 0) {
this.runTask();
} else {
this.dispatchEvent(new CustomEvent(AsyncTaskEvent.IDLE));
}
};
async runTask() {
this.runningTaskCount++;
const [task, resolve, reject] = this.taskQueue.shift()!;
try {
const res = await task();
resolve(res);
} catch (err) {
reject(err);
} finally {
this.runningTaskCount--;
this.dispatchEvent(new CustomEvent('task:done'));
}
}
async addTask(task: Task) {
return new Promise((resolve, reject) => {
this.taskQueue.push([task, resolve, reject]);
this.dispatchEvent(new CustomEvent('task:add'));
});
}
}
export { AsyncTaskEvent };
export default AsyncTask;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment