A simple queue [ts playground](https://www.typescriptlang.org/play?#code/PQKhCgAIUgXALAlgZ0gYwDYENmpZAV2QFMATOAe0gEcDi7IcBPAOzThwGtkA6KEYOGIAPAA4UATrHTZckAILJWaAIp0GAbyiRRBAEYZE7CcSykKLDExrriALkgAKRwEpIAXgB8kAAoSKALYoxAA8AG4UiKSeLgDaALoekAkA3ODaoBCQ2TC6yPCMHMiclHDwxDb0xDyQAJIAZmUVtFWQ+MQBorBMADRNRSUA7ogYGJB6FSLEaASwZG0BAWSIWHNWfNnQgtl58I6wXA6uHt5+gcHhkdEuDhFRkFqbZSg8LXQ8u-tcLmlPiI37JC8N7VDDEFgAcwQHnc7kgAEY3I8ns9eBICCxXL9NgBfbR4jJgbTQSAmGYSZCIMLEKykjH9A7FPAsfogjY5SAAZVgFFEkEG5RZCGatjaqA6XSY7K22lEEipqwqzDYdMxN18-iCJEuUW8yOyaAsyGkjJKcIQLxBsQADPFsdl-k4AISmtwmWAECQse1wCTWfWbLCDLCIE1cLHEyA49CrNAFRzECT+CRIyMGo0UME8RPJxwAAwAoknJJApjNYIhIQMHAASDQ5yQ4vM-SPR+qVrCjf1p1GvWw8fL-WARp54p5BkMmoE8dFq7F4gmGljGyoMOEsYiDBRKNhqKoR8BLlem+FJZXsY5eB7aCehyAbrdnLXEZwmZCZ6luK8Bo+Z0EUCFHAAIgAFS4BFIGNLApDIICWyeEhYBAxAlgoWZHDfD9iD6AAma18PgqMXB4YVMUvPVI1-LMMAA4CwOKCDDU6ME5lIOD5xbHE0kPI0w2KHCzx3C8vwo7Jb2kB8NXObU7miV9iHfDBqT6EwACtplgETryeKj-0A0DwIEqCYLYwjskQ5DUPQ8jtJRNSNMcSSi1zAyGIE8FDQxOYTHILAWQbCQ4LMqM+nhfDrUInFiNI5wtJ-DNqNo1ySgEgBhQJRBY2DIs47ijz4zgAGZBOUJw4pvYM70kp8Llkzx5MUz8Tls9Nlz-HgaP0+iSmK4zWPYyMLJQ4g0OHGyA2yTClJfYKcT6QrwpykjBVi5r4raxKuvA4qmMy4h+pytIuPSNlPhPFtTqIPZTRwi7+zOrhCpbIA) ```ts /** * this class is used to queue async tasks. */ export class AsyncQueue { public readonly queue: (() => Promise<void>)[] = []; /** * push a task to the queue. If the queue is empty, the task will be executed immediately. */ push(task: () => Promise<void>): void { this.queue.push(task); if (this.queue.length === 1) { this.run(); } } /** * recursively run the tasks in the queue. * Stop when the queue is empty. */ private async run(): Promise<void> { const task = this.queue[0]; if (!task) return; try { await task(); } catch (error) { console.error(`Error executing task: ${error}`); } finally { this.queue.shift(); } await this.run(); } } const queue = new AsyncQueue(); const task1 = async () => { await new Promise((resolve) => { console.log("Task 1 started"); setTimeout(resolve, 2000); }).then(() => { console.log("Task 1 completed"); }); }; const task2 = async () => { await new Promise<void>((resolve, reject) => { console.log("Task 2 started"); setTimeout(() => { reject(new Error("Task 2 encountered an error")); }, 1000); }).then(() => { console.log("Task 2 Completed"); }); }; const task3 = async () => { await new Promise<void>((resolve) => { console.log("Task 3 started"); setTimeout(() => { resolve(); }, 3000); }).then(() => { console.log("Task 3 completed"); }); }; queue.push(task1); queue.push(task2); queue.push(task3); ```