main
ts 44 lines 1.59 KB
Raw
1 import { Readable } from 'stream'
2 import { isAsyncIterable } from './cross'
3
4 // produces as promises resolve, not sequentially
5 export class AsapStream<T> extends Readable {
6 finished = false
7 constructor(private promises: Iterable<Promise<T> | T> | AsyncIterable<Promise<T> | T>) {
8 super({ objectMode: true })
9 }
10 _read() {
11 if (this.finished) return
12 this.finished = true
13 void (async () => {
14 const pending: Promise<T>[] = []
15 try {
16 if (isAsyncIterable(this.promises)) {
17 const iterator = this.promises[Symbol.asyncIterator]()
18 while (true) {
19 const { value, done } = await iterator.next()
20 if (done) break
21 const promise = Promise.resolve(value)
22 pending.push(promise)
23 promise.then(x => x !== undefined && this.push(x),
24 e => this.emit('error', e) )
25 }
26 }
27 else {
28 for (const p of this.promises) {
29 const promise = Promise.resolve(p)
30 pending.push(promise)
31 promise.then(x => x !== undefined && this.push(x),
32 e => this.emit('error', e) )
33 }
34 }
35 await Promise.allSettled(pending)
36 this.push(null)
37 }
38 catch (e) {
39 this.emit('error', e)
40 this.push(null)
41 }
42 })()
43 }
44 }