@johngw/stream
Version:
Reactive programming tools using the WHATWG Streams API.
109 lines • 2.69 kB
JavaScript
import { assertNever } from 'assert-never';
import { isArrayLike, isAsyncIterable, isIterable, isIteratorOrAsyncIterator, } from '@johngw/stream-common/Object';
/**
* Creates a readable stream from an collection of values.
*
* @group Sources
* @example
* Using an iterable
* ```
* fromCollection([1, 2, 3, 4])
* ```
*
* Using an Async Iterable
* ```
* fromCollection((async function* () {
* yield 1
* })())
* ```
*
* Using an ArrayLike
* ```
* fromCollection({
* 0: 'zero',
* 1: 'one',
* 2: 'two',
* length: 3,
* })
* ```
*/
export function fromCollection(collection, queuingStrategy) {
return new ReadableStream(isIterable(collection)
? new IteratorSource(collection[Symbol.iterator]())
: isAsyncIterable(collection)
? new IteratorSource(collection[Symbol.asyncIterator]())
: isIteratorOrAsyncIterator(collection)
? new IteratorSource(collection)
: isArrayLike(collection)
? new ArrayLikeSource(collection)
: assertNever(collection), queuingStrategy);
}
/**
* An underlying source for an `Iterator` or `AsyncIterator`.
*
* @group Sources
* @example
* ```
* const reader = new ReadableStream(new IteratorSource((function* () {
* yield 1
* yield 2
* })()))
* ```
*/
export class IteratorSource {
#iterator;
constructor(iterator) {
this.#iterator = iterator;
}
async pull(controller) {
while (controller.desiredSize) {
let result;
try {
result = await this.#iterator.next();
}
catch (error) {
return controller.error(error);
}
if (result.done)
return controller.close();
else
controller.enqueue(result.value);
}
}
}
/**
* An underlying source for an `ArrayLike`.
*
* @group Sources
* @example
* ```
* const reader = new ReadableStream(new ArrayLikeSource({
* 0: 'zero',
* 1: 'one',
* length: 2
* }))
* ```
*/
export class ArrayLikeSource {
#arrayLike;
#length;
#i = 0;
constructor(arrayLike) {
this.#arrayLike = arrayLike;
this.#length = arrayLike.length;
}
start(controller) {
if (this.#finished)
controller.close();
}
pull(controller) {
for (; controller.desiredSize && this.#i < this.#length; this.#i++)
controller.enqueue(this.#arrayLike[this.#i]);
if (this.#finished)
controller.close();
}
get #finished() {
return this.#i === this.#length;
}
}
//# sourceMappingURL=fromCollection.js.map