|
import { Subject } from '../Subject'; |
|
import { Observable } from '../Observable'; |
|
import { Subscriber } from '../Subscriber'; |
|
import { Subscription } from '../Subscription'; |
|
import { refCount as higherOrderRefCount } from '../operators/refCount'; |
|
import { createOperatorSubscriber } from '../operators/OperatorSubscriber'; |
|
import { hasLift } from '../util/lift'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
if (hasLift(source)) { |
|
this.lift = source.lift; |
|
} |
|
} |
|
|
|
|
|
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( |
|
createOperatorSubscriber( |
|
subject as any, |
|
undefined, |
|
() => { |
|
this._teardown(); |
|
subject.complete(); |
|
}, |
|
(err) => { |
|
this._teardown(); |
|
subject.error(err); |
|
}, |
|
() => this._teardown() |
|
) |
|
) |
|
); |
|
|
|
if (connection.closed) { |
|
this._connection = null; |
|
connection = Subscription.EMPTY; |
|
} |
|
} |
|
return connection; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
refCount(): Observable<T> { |
|
return higherOrderRefCount()(this) as Observable<T>; |
|
} |
|
} |
|
|