@thi.ng/rstream
Version:
Reactive streams & subscription primitives for constructing dataflow graphs / pipelines
97 lines (96 loc) • 2.19 kB
JavaScript
import { EquivMap } from "@thi.ng/associative/equiv-map";
import { unsupported } from "@thi.ng/errors/unsupported";
import { __optsWithID } from "./idgen.js";
import { LOGGER } from "./logger.js";
import { Subscription, subscription } from "./subscription.js";
const pubsub = (opts) => new PubSub(opts);
class PubSub extends Subscription {
topicfn;
topics;
constructor(opts) {
super(
void 0,
__optsWithID("pubsub", {
xform: opts.xform
})
);
this.topicfn = opts.topic;
this.topics = new EquivMap(void 0, {
equiv: opts.equiv
});
}
/**
* Unsupported. Use {@link PubSub.subscribeTopic} instead.
*/
subscribe() {
return unsupported(`use subscribeTopic() instead`);
}
/**
* Unsupported. Use {@link PubSub.subscribeTopic} instead.
*/
transform() {
return unsupported(`use subscribeTopic() instead`);
}
subscribeTopic(topicID, sub, opts) {
let t = this.topics.get(topicID);
!t && this.topics.set(
topicID,
t = subscription(
void 0,
__optsWithID("topic", { closeOut: "never" })
)
);
return t.subscribe(sub, opts);
}
transformTopic(topicID, xform, opts = {}) {
return this.subscribeTopic(
topicID,
{ error: opts.error },
{
...opts,
xform
}
);
}
unsubscribeTopic(topicID, sub) {
const t = this.topics.get(topicID);
return t ? t.unsubscribe(sub) : false;
}
unsubscribe(sub) {
if (!sub) {
for (let t of this.topics.values()) {
t.unsubscribe();
}
this.topics.clear();
return super.unsubscribe();
}
return unsupported();
}
done() {
for (let t of this.topics.values()) {
t.done();
}
super.done();
}
dispatch(x) {
LOGGER.debug(this.id, "dispatch", x);
this.cacheLast && (this.last = x);
const t = this.topicfn(x);
if (t !== void 0) {
const sub = this.topics.get(t);
if (sub) {
try {
sub.next?.(x);
} catch (e) {
if (!sub.error || !sub.error(e)) {
return this.unhandledError(e);
}
}
}
}
}
}
export {
PubSub,
pubsub
};