-
Notifications
You must be signed in to change notification settings - Fork 0
/
lazyMergeStream.ts
33 lines (33 loc) · 1.07 KB
/
lazyMergeStream.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/** pull upstream only when downstream pulled */
export function lazyMergeStream(...streams: ReadableStream[]) {
// skip merge if only one
if (streams.length === 1) return streams[0];
const never = new Promise<never>(() => {});
const readers = streams.map((s) => s.getReader());
const reads = streams.map(() => null as null | Promise<never | undefined>);
const dones: (() => void)[] = [];
const allDone = Promise.all(
streams.map(() => new Promise<void>((resolve) => void dones.push(resolve))),
);
return new ReadableStream(
{
start: (ctrl) => void allDone.then(() => ctrl.close()),
cancel: (reason) => void readers.map((r) => r.cancel(reason)),
pull: (ctrl) =>
Promise.race(
readers.map(
(r, i) =>
(reads[i] ??= r.read().then(({ value, done }) => {
if (done) {
dones[i]();
return never;
}
ctrl.enqueue(value);
reads[i] = null;
})),
),
),
},
{ highWaterMark: 0 },
);
}