deno.land / std@0.224.0 / async / tee.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.// This module is browser compatible.
/** Utility for representing n-tuple. Used in {@linkcode tee}. */export type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : TupleOf<T, N, []> : never;
/** Utility for representing n-tuple of. Used in {@linkcode Tuple}. */export type TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N ? R : TupleOf<T, N, [T, ...R]>;
interface QueueNode<T> { value: T; next: QueueNode<T> | undefined;}
class Queue<T> { #source: AsyncIterator<T>; #queue: QueueNode<T>; head: QueueNode<T>;
done: boolean;
constructor(iterable: AsyncIterable<T>) { this.#source = iterable[Symbol.asyncIterator](); this.#queue = { value: undefined!, next: undefined, }; this.head = this.#queue; this.done = false; }
async next() { const result = await this.#source.next(); if (!result.done) { const nextNode: QueueNode<T> = { value: result.value, next: undefined, }; this.#queue.next = nextNode; this.#queue = nextNode; } else { this.done = true; } }}
/** * Branches the given async iterable into the `n` branches. * * @example * ```ts * import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts"; * * const gen = async function* gen() { * yield 1; * yield 2; * yield 3; * }; * * const [branch1, branch2] = tee(gen()); * * for await (const n of branch1) { * console.log(n); // => 1, 2, 3 * } * * for await (const n of branch2) { * console.log(n); // => 1, 2, 3 * } * ``` */export function tee<T, N extends number = 2>( iterable: AsyncIterable<T>, n: N = 2 as N,): Tuple<AsyncIterable<T>, N> { const queue = new Queue<T>(iterable);
async function* generator(): AsyncGenerator<T> { let buffer = queue.head; while (true) { if (buffer.next) { buffer = buffer.next; yield buffer.value; } else if (queue.done) { return; } else { await queue.next(); } } }
return Array.from({ length: n }).map( () => generator(), ) as Tuple< AsyncIterable<T>, N >;}
Version Info