improve async queue

resolve the promise for the added task immediately, instead of waiting on a promise for all tasks
This commit is contained in:
itsMapleLeaf
2022-08-07 12:55:47 -05:00
parent ac3df750bc
commit bbf3c4ab17

View File

@@ -1,25 +1,35 @@
export type AsyncCallback = () => unknown export type AsyncCallback<T> = () => T
type QueueItem = {
callback: AsyncCallback<unknown>
resolve: (value: unknown) => void
reject: (error: unknown) => void
}
export class AsyncQueue { export class AsyncQueue {
private callbacks: AsyncCallback[] = [] private items: QueueItem[] = []
private promise: Promise<void> | undefined private running = false
async add(callback: AsyncCallback) { add<T>(callback: AsyncCallback<T>): Promise<Awaited<T>> {
this.callbacks.push(callback) return new Promise((resolve, reject) => {
if (this.promise) return this.promise this.items.push({ callback, resolve: resolve as any, reject })
void this.runQueue()
this.promise = this.runQueue() })
try {
await this.promise
} finally {
this.promise = undefined
}
} }
private async runQueue() { private async runQueue() {
let callback: AsyncCallback | undefined if (this.running) return
while ((callback = this.callbacks.shift())) { this.running = true
await callback()
let item
while ((item = this.items.shift())) {
try {
item.resolve(await item.callback())
} catch (error) {
item.reject(error)
}
} }
this.running = false
} }
} }