@johngw/stream
Version:
Reactive programming tools using the WHATWG Streams API.
79 lines • 2.5 kB
JavaScript
import { ControllableSource } from '../sources/ControllableSource.js';
import { SourceComposite } from '../sources/SourceComposite.js';
/**
* A ForkableSink is the underlying logic for "1 Writable to many Readables".
*
* @group Sinks
* @see {@link ForkableStream:class}
* @example
* ```
* const forkable = new ForkableSink<T>()
* const writable = new WritableStream(forkable)
*
* fromCollection([1, 2, 3, 4, 5, 6, 7]).pipeTo(writable)
*
* forkable.fork().pipeTo(write(x => console.info('fork1', x)))
* // fork1 1, fork1 2, fork1 3, fork1 4, fork1 5, fork1 6, fork1 7
*
* forkable.fork().pipeTo(write(x => console.info('fork2', x)))
* // fork2 1, fork2 2, fork2 3, fork2 4, fork2 5, fork2 6, fork2 7
* ```
*/
export class ForkableSink {
#error;
#finished = false;
#controllers = new Map();
abort(reason) {
for (const [controller] of this.#controllers)
controller.error(reason);
this.#controllers.clear();
this.#error = reason;
this.#finished = true;
}
close() {
for (const [controller] of this.#controllers) {
try {
controller.close();
}
catch (error) {
// potentially already closed
}
}
this.#controllers.clear();
this.#finished = true;
}
write(chunk) {
for (const [controller] of this.#controllers)
if (controller.desiredSize)
controller.enqueue(chunk);
}
get finished() {
return this.#finished;
}
fork(underlyingSource, queuingStrategy) {
return this._pipeThroughController(this._addController(underlyingSource, queuingStrategy));
}
_addController(underlyingSource = {}, queuingStrategy) {
const controller = new ControllableSource();
const stream = new ReadableStream(new SourceComposite([
controller,
underlyingSource,
{
cancel: () => {
this.#controllers.delete(controller);
},
},
]), queuingStrategy);
if (!this.#finished)
this.#controllers.set(controller, stream);
return [controller, stream];
}
_pipeThroughController([controller, stream]) {
if (this.#error)
controller.error(this.#error);
else if (this.#finished)
controller.close();
return stream;
}
}
//# sourceMappingURL=ForkableSink.js.map