Hacker News new | ask | show | jobs
by tekkk 348 days ago
While I'm at it, here's my version, if people want to see and give feedback:

  export interface AsyncQueueOptions {
    timeoutSeconds?: number
  }

  export class AsyncQueue<T> {
    private readonly queue: Promise<T | undefined>[] = []
    readonly timeoutSeconds: number
    private timeout: ReturnType<typeof setTimeout> | undefined
    private reject = () => {}
    private resolve = (value: T | PromiseLike<T>) => {}

    /**
     * @param timeoutSeconds @default 25
     */
    constructor({ timeoutSeconds = 25 }: AsyncQueueOptions = {}) {
      this.timeoutSeconds = timeoutSeconds
      if (timeoutSeconds > 100) {
        console.warn(`You are initializing AsyncQueue with over 100s timeout: ${timeoutSeconds}`)
      }
      this.queue.push(
        new Promise<T | undefined>((resolve, reject) => {
          this.resolve = resolve
          this.reject = reject
          this.timeout = setTimeout(() => resolve(undefined), timeoutSeconds * 1000)
        })
      )
    }

    next(): Promise<T | undefined> | undefined {
      return this.queue.shift()
    }

    push(msg: T) {
      this.resolve(msg)
      this.queue.push(
        new Promise<T | undefined>((resolve, reject) => {
          this.resolve = resolve
          this.reject = reject
          clearTimeout(this.timeout)
          this.timeout = setTimeout(() => resolve(undefined), this.timeoutSeconds * 1000)
        })
      )
    }

    close(msg?: T) {
      if (msg) {
        this.resolve(msg)
      }
      clearTimeout(this.timeout)
    }
  }