| 35 | |
| 36 | /** An AsyncIterable wrapper that caches so that it can be iterated multiple times */ |
| 37 | export function reiterable<T>(iterable: AsyncIterable<T>): AsyncIterable<T> { |
| 38 | const cache = new Array<T>(); |
| 39 | let done: boolean | undefined; |
| 40 | let nextElement: undefined | Promise<IteratorResult<T>>; |
| 41 | |
| 42 | return { |
| 43 | [Symbol.asyncIterator]() { |
| 44 | let index = 0; |
| 45 | return { |
| 46 | async next() { |
| 47 | if (index < cache.length) { |
| 48 | return { value: cache[index++], done: false }; |
| 49 | } |
| 50 | if (done) { |
| 51 | return { value: undefined, done: true }; |
| 52 | } |
| 53 | index++; |
| 54 | if (!is.promise(nextElement)) { |
| 55 | nextElement = iterable[Symbol.asyncIterator]().next().then(element => { |
| 56 | if (!(done = element.done)) { |
| 57 | cache.push(element.value); |
| 58 | } |
| 59 | nextElement = undefined; |
| 60 | return element; |
| 61 | }); |
| 62 | } |
| 63 | return nextElement; |
| 64 | } |
| 65 | }; |
| 66 | } |
| 67 | }; |
| 68 | } |
| 69 | |
| 70 | export type AsynchIterable<T> = AsyncIterable<T> & { |
| 71 | add(...iterables: (Some<T> | undefined | Promise<T> | Promise<undefined | T>)[]): void; |