import { assert } from "./assert"; export type Subscription = (value: T) => void; export type Unsubscribe = () => void; type Observer = (subscriber: Subscriber) => Unsubscribe; export type Observable = { subscribe(handler: Subscription): Unsubscribe; toRxObserver(): (subscriber: Subscriber) => Unsubscribe; } type Subscriber = { next(value?: T): void; error?(error: any): void; complete?(): void; } /** * * * @export * @class EventBus * @implements {Observable} * @template T */ export class EventBus implements Observable { private readonly _subscriptions = new Map, Unsubscribe>(); private readonly _onComplete = new Set>(); private _completed = false; /** * * * @param {T} value * @returns {this} * @memberof EventBus */ emit(value: T): this { for (const subscription of this._subscriptions.keys()) { subscription(value); } return this; } /** * * * @param {Subscription} handler * @returns {Unsubscribe} {Unsubscribe} * @memberof EventBus */ subscribe(handler: Subscription): Unsubscribe { assert(!this._completed, "Completed"); const cached = this._subscriptions.get(handler); if (cached) return cached; const unsubscribe = () => { this._subscriptions.delete(handler); }; this._subscriptions.set(handler, unsubscribe); return unsubscribe; } /** * * * @memberof EventBus * @returns {void} */ complete(): void { if (this._completed) return; this._completed = true; for (const unsubscribe of this._subscriptions.values()) { unsubscribe(); } for (const complete of this._onComplete) { complete(); this._onComplete.delete(complete); } } /** * * * @returns {Observer} * @example * import { Observable } from "rxjs"; * * const bus = new EventBus(); * const observable = new Observable(bus.toRxObserver()); * // Observable */ toRxObserver(): Observer { return (subscriber) => { this._onComplete.add(() => subscriber.complete?.()); return this.subscribe((value) => subscriber.next(value)); }; } }