UNPKG

rxjs

Version:

Reactive Extensions for modern JavaScript

75 lines (66 loc) 2 kB
/** @prettier */ import { Subject } from '../Subject'; import { Observable } from '../Observable'; import { Subscriber } from '../Subscriber'; import { Subscription } from '../Subscription'; import { refCount as higherOrderRefCount } from '../operators/refCount'; import { OperatorSubscriber } from '../operators/OperatorSubscriber'; /** * @class ConnectableObservable<T> */ export class ConnectableObservable<T> extends Observable<T> { protected _subject: Subject<T> | null = null; protected _refCount: number = 0; protected _connection: Subscription | null = null; constructor(public source: Observable<T>, protected subjectFactory: () => Subject<T>) { super(); } protected _subscribe(subscriber: Subscriber<T>) { return this.getSubject().subscribe(subscriber); } protected getSubject(): Subject<T> { const subject = this._subject; if (!subject || subject.isStopped) { this._subject = this.subjectFactory(); } return this._subject!; } protected _teardown() { this._refCount = 0; const { _connection } = this; this._subject = this._connection = null; _connection?.unsubscribe(); } connect(): Subscription { let connection = this._connection; if (!connection) { connection = this._connection = new Subscription(); const subject = this.getSubject(); connection.add( this.source.subscribe( new OperatorSubscriber( subject as any, undefined, (err) => { this._teardown(); subject.error(err); }, () => { this._teardown(); subject.complete(); }, () => this._teardown() ) ) ); if (connection.closed) { this._connection = null; connection = Subscription.EMPTY; } } return connection; } refCount(): Observable<T> { return higherOrderRefCount()(this) as Observable<T>; } }