@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
73 lines (72 loc) • 1.88 kB
JavaScript
import { assert } from "@thi.ng/errors/assert";
import { State } from "./api.js";
import { __optsWithID } from "./idgen.js";
import { Subscription } from "./subscription.js";
const metaStream = (factory, opts) => new MetaStream(factory, opts);
class MetaStream extends Subscription {
factory;
stream;
sub;
emitLast;
doneRequested;
constructor(factory, opts = {}) {
super(void 0, __optsWithID("metastram", opts));
this.factory = factory;
this.emitLast = opts.emitLast === true;
this.doneRequested = false;
}
next(x) {
if (this.state < State.DONE) {
if (this.stream) {
this.stream.unsubscribe(this.sub);
}
let stream = this.factory(x);
if (stream) {
this.stream = stream;
this.sub = this.stream.subscribe({
next: (x2) => {
stream === this.stream && super.dispatch(x2);
this.doneRequested && this.done();
},
done: () => {
this.stream.unsubscribe(this.sub);
if (stream === this.stream) {
this.stream = void 0;
this.sub = void 0;
}
},
error: (e) => super.error(e),
__owner: this
});
}
}
}
done() {
if (this.emitLast && !this.doneRequested) {
this.doneRequested = true;
} else {
if (this.stream) {
this.detach(true);
}
this.closeIn !== "never" && super.done();
}
}
unsubscribe(sub) {
if (this.stream && (!sub || this.subs.length === 1)) {
this.detach(!sub);
}
return super.unsubscribe(sub);
}
detach(force) {
if (force || this.closeOut !== "never") {
assert(!!this.stream, "input stream already removed");
this.stream.unsubscribe(this.sub);
delete this.stream;
delete this.sub;
}
}
}
export {
MetaStream,
metaStream
};