From bbf3c4ab17e911c2df982e862c705e932215be47 Mon Sep 17 00:00:00 2001 From: itsMapleLeaf <19603573+itsMapleLeaf@users.noreply.github.com> Date: Sun, 7 Aug 2022 12:55:47 -0500 Subject: [PATCH] improve async queue resolve the promise for the added task immediately, instead of waiting on a promise for all tasks --- packages/helpers/async-queue.ts | 42 ++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/helpers/async-queue.ts b/packages/helpers/async-queue.ts index 5837b78..f9421a7 100644 --- a/packages/helpers/async-queue.ts +++ b/packages/helpers/async-queue.ts @@ -1,25 +1,35 @@ -export type AsyncCallback = () => unknown +export type AsyncCallback = () => T + +type QueueItem = { + callback: AsyncCallback + resolve: (value: unknown) => void + reject: (error: unknown) => void +} export class AsyncQueue { - private callbacks: AsyncCallback[] = [] - private promise: Promise | undefined + private items: QueueItem[] = [] + private running = false - async add(callback: AsyncCallback) { - this.callbacks.push(callback) - if (this.promise) return this.promise - - this.promise = this.runQueue() - try { - await this.promise - } finally { - this.promise = undefined - } + add(callback: AsyncCallback): Promise> { + return new Promise((resolve, reject) => { + this.items.push({ callback, resolve: resolve as any, reject }) + void this.runQueue() + }) } private async runQueue() { - let callback: AsyncCallback | undefined - while ((callback = this.callbacks.shift())) { - await callback() + if (this.running) return + this.running = true + + let item + while ((item = this.items.shift())) { + try { + item.resolve(await item.callback()) + } catch (error) { + item.reject(error) + } } + + this.running = false } }