@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
71 lines (70 loc) • 2.02 kB
JavaScript
import { dedupe } from "@thi.ng/transducers/dedupe";
import { range } from "@thi.ng/transducers/range";
import { __optsWithID } from "./idgen.js";
import { Subscription, subscription } from "./subscription.js";
const fromObject = (src, opts = {}) => new StreamObj(src, opts);
const fromTuple = (src, opts) => new StreamObj(src, { keys: [...range(src.length)], ...opts });
class StreamObj extends Subscription {
/**
* Object of managed & typed streams for registered keys.
*/
keys;
streams = {};
defaults;
constructor(src, opts = {}) {
super(void 0, __optsWithID("obj", opts));
this.keys = opts.keys || Object.keys(src);
this.defaults = opts.defaults;
const _opts = opts.dedupe !== false ? {
xform: dedupe(opts.equiv || ((a, b) => a === b)),
...opts
} : opts;
for (const k of this.keys) {
this.streams[k] = subscription(void 0, {
..._opts,
id: `${this.id}-${k}`
});
}
opts.initial !== false && this.next(src);
}
/**
* Receives an object of configured type and feeds each key's new value into
* its respective {@link StreamObj.streams}. If the
* {@link StreamObjOpts.defaults} option is given, `undefined` key values
* are replaced with their specified default. If
* {@link StreamObjOpts.dedupe} is enabled (default) only changed values (as
* per {@link StreamObjOpts.equiv} predicate option) will be propagated
* downstream.
*
* @param x -
*/
next(x) {
this.cacheLast && (this.last = x);
for (const k of this.keys) {
const val = x[k];
this.streams[k].next(
this.defaults && val === void 0 ? this.defaults[k] : val
);
}
super.next(x);
}
done() {
for (const k of this.keys) {
this.streams[k].done?.();
}
super.done();
}
unsubscribe(sub) {
if (!sub) {
for (const k of this.keys) {
this.streams[k].unsubscribe();
}
}
return super.unsubscribe(sub);
}
}
export {
StreamObj,
fromObject,
fromTuple
};