@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
125 lines • 4.01 kB
TypeScript
import type { Fn, Nullable } from "@thi.ng/api";
import { type CommonOpts, type ISubscription } from "./api.js";
import { Subscription } from "./subscription.js";
export interface MetaStreamOpts extends CommonOpts {
/**
* If true, emits the last received value from the metastream's
* current child stream (if any) when the metastream's parent is
* calling `.done()`.
*
* @defaultValue false
*/
emitLast: boolean;
}
/**
* Returns a {@link Subscription} which transforms each incoming value into a
* new {@link ISubscription}, subscribes to it (via an hidden / internal
* subscription) and then only passes values from that stream to its own
* subscribers.
*
* @remarks
* If a new value is received, the metastream first unsubscribes from any still
* active previous stream (if any), before creating and subscribing to the new
* one. Hence this stream type is useful for cases where streams need to be
* dynamically created & inserted into an existing dataflow topology.
*
* The user supplied `factory` function will be called for each incoming value
* and is responsible for creating the new stream instances. If the function
* returns null/undefined, no further action will be taken (acts like a filter
* transducer).
*
* The factory function does NOT need to create *new* streams, but can merely
* return other existing streams, and so making the meta stream act like a
* switch with arbitrary criteria. However, if the meta stream itself is the
* only subscriber to such existing input streams, you'll need to configure the
* input's {@link CommonOpts.closeOut} option to keep them alive and support
* dynamic switching between them.
*
* @example
* ```ts tangle:../export/metastream.ts
* import { fromIterable, metaStream, trace } from "@thi.ng/rstream";
* import { repeat } from "@thi.ng/transducers";
*
* // transform each received odd number into a stream
* // producing 3 copies of that number in the metastream
* // even numbers are ignored
* const a = metaStream<number, number>(
* (x) => (x & 1)
* ? fromIterable(repeat(x, 3), { delay: 100 })
* : null
* );
*
* a.subscribe(trace())
* a.next(23)
*
* // 23
* // 23
* // 23
*
* setTimeout(() => a.next(42), 500); // value 42 ignored by metastream
*
* setTimeout(() => a.next(43), 1000);
* // 43
* // 43
* // 43
* ```
*
* @example
* ```ts tangle:../export/metastream-2.ts
* import { fromIterable, metaStream, trace } from "@thi.ng/rstream";
* import { cycle, repeat } from "@thi.ng/transducers";
*
* // infinite inputs (important: closeOut mode = "never"!)
* const a = fromIterable(
* repeat("a"),
* { delay: 100, closeOut: "never" }
* );
* const b = fromIterable(
* repeat("b"),
* { delay: 100, closeOut: "never" }
* );
*
* // stream selector / switch
* const m = metaStream<boolean, string>((x) => (x ? a : b));
* m.subscribe(trace("meta from: "));
*
* // create infinite stream of true/false and pipe into
* // the metastream and switch which source to use
* fromIterable(cycle([true, false]), { delay: 500 })
* .subscribe({ next(x) { m.next(x); } });
*
* // a
* // a
* // a
* // a
* // a
* // b
* // b
* // b
* // b
* // b
* // a
* // a
* // ...
* ```
*
* @param factory -
* @param id -
*/
export declare const metaStream: <A, B>(factory: Fn<A, Nullable<ISubscription<B, B>>>, opts?: Partial<MetaStreamOpts>) => MetaStream<A, B>;
/**
* See {@link metaStream} for reference & examples.
*/
export declare class MetaStream<A, B> extends Subscription<A, B> {
factory: Fn<A, Nullable<ISubscription<B, B>>>;
stream?: ISubscription<B, B>;
sub?: ISubscription<B, B>;
emitLast: boolean;
doneRequested: boolean;
constructor(factory: Fn<A, Nullable<ISubscription<B, B>>>, opts?: Partial<MetaStreamOpts>);
next(x: A): void;
done(): void;
unsubscribe(sub?: ISubscription<B, any>): boolean;
protected detach(force: boolean): void;
}
//# sourceMappingURL=metastream.d.ts.map