Skip to content

Instantly share code, notes, and snippets.

@sidola
Created April 24, 2021 20:12
Show Gist options
  • Save sidola/6d4c59cd8b0e6db2a149b9a4110e3122 to your computer and use it in GitHub Desktop.
Save sidola/6d4c59cd8b0e6db2a149b9a4110e3122 to your computer and use it in GitHub Desktop.
import { assertDefined } from './utils'
type AsyncFunc<T> = () => Promise<T>
export class MagicQueue<T> {
private isActive = false
private isKilled = false
private queue: AsyncFunc<T>[] = []
constructor(private options: {
onSuccess: (item: T) => void
onError: (error: unknown) => void
onStart: () => void
onEnd: () => void
}) { }
push(fn: AsyncFunc<T>) {
this.isKilled = false
this.queue.push(fn)
this.run()
}
kill() {
this.isActive = false
this.isKilled = true
}
private run() {
if (this.isActive || this.isKilled || this.queue.length <= 0) {
return
}
this.isActive = true
this.options.onStart()
const fn = this.queue.pop()
assertDefined(fn)
fn().then((result) => this.handleThen(result))
.catch((error) => this.options.onError(error))
}
private handleThen(result: T) {
if (this.isKilled) {
return
}
this.options.onSuccess(result)
if (this.queue.length <= 0) {
this.isActive = false
this.options.onEnd()
return
}
const nextFn = this.queue.pop()
assertDefined(nextFn)
nextFn()
.then((result) => this.handleThen(result))
.catch((error) => this.options.onError(error))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment