UNPKG

@benev/slate

Version:
78 lines 2.6 kB
import { Op } from "../op/op.js"; import { ob } from "../tools/ob.js"; import { Signal } from "./signal.js"; import { OpSignal } from "./op_signal.js"; import { SignalTracker } from "./parts/tracker.js"; export class SignalTower { // TODO wrap all signals in WeakRef, to promote garbage collection? #signals = new Set(); #waiters = new Set(); signal(value) { const signal = new Signal(value); this.#signals.add(signal); return signal; } computed(fun) { const signal = this.signal(fun()); this.reaction(() => { signal.value = fun(); }); return signal; } async computedAsync(collector, responder) { const value = await responder(collector()); const signal = this.signal(value); this.reaction(collector, async (x) => { signal.value = await responder(x); }); return signal; } op(op = Op.loading()) { const signal = new OpSignal(op); this.#signals.add(signal); return signal; } load(fn) { const signal = this.op(Op.loading()); signal.load(fn); return signal; } many(states) { return (ob(states).map(state => this.signal(state))); } reaction(collector, responder) { const tracker = new SignalTracker({ waiters: this.#waiters, all_signals: this.#signals, }); const track = { collector, responder }; const { recording } = tracker.observe(track.collector); tracker.add_listeners(track, recording); return () => tracker.shutdown(); } lean(actor) { const tracker = new SignalTracker({ waiters: this.#waiters, all_signals: this.#signals, }); const track = { lean: true, actor }; return { stop: () => tracker.shutdown(), collect: collector => { const { payload, recording } = tracker.observe(collector); tracker.add_listeners(track, recording); return payload; }, }; } // TODO this is a hack, we shouldn't have to wait two cycles to be sure everything's done async #waitOneCycle() { return await Promise.all([...this.#signals].map(s => s.wait)) .then(() => Promise.all([...this.#waiters])) .then(() => { this.#waiters.clear(); }); } get wait() { return Promise.resolve() .then(() => this.#waitOneCycle()) .then(() => this.#waitOneCycle()); } } //# sourceMappingURL=tower.js.map