import { Scheduler, Sink, Stream, Time } from '@motorcycle/types' import { MulticastSource } from '@most/core' /** * Deliver the most recently seen event to each new observer the instant it * begins observing. A held stream is always multicast. * * Given an input stream: * * ``` * stream: -a---b---c---d-> * ``` * * observers which begin observing at different times will see: * * ``` * observer1: -a---b---c---d-> * observer2: a-b---c---d-> * observer3: c--d-> * ``` * * @name hold(stream: Stream): Stream * * @example * import { createDocumentDomSource events } from '@motorcycle/dom' * import { drain, hold, map } from @motorcycle/stream' * * const doc = createDocumentDomSource(now(document)) * * // start holding on first subscription * const click$ = hold(map(e => ({ x: e.clientX, y: e.clientY }), events('click', doc))) * * // hold the latest event even before the first subscription * drain(click$) */ export function hold(stream: Stream): Stream { return new Hold(stream) } class Hold extends MulticastSource implements Stream { private has: boolean private value: A private scheduler: Scheduler constructor(stream: Stream) { super(stream) } public run(sink: Sink, scheduler: Scheduler) { this.scheduler = scheduler return super.run(sink, scheduler) } public add(sink: Sink) { if (this.has) sink.event(this.scheduler.currentTime(), this.value) return super.add(sink) } public event(time: Time, value: A) { this.has = true this.value = value return super.event(time, value) } }