UNPKG

@acutmore/rxjs

Version:

Reactive Extensions for modern JavaScript

247 lines (199 loc) 5.66 kB
// v4-backwards-compatibility import {ISubscription} from '../internal/Subscription'; export class DisposableImpl implements ISubscription { private _disposed = false; constructor(private work: () => void) {} get closed() { return this._disposed; } get isDisposed() { return this._disposed; } unsubscribe(): void { if (!this._disposed) { this._disposed = true; if (this.work !== undefined) { this.work(); } } } dispose: this['unsubscribe']; }; DisposableImpl.prototype.dispose = function() { this.unsubscribe(); }; export class Disposable implements ISubscription { static create(fn: () => void): Disposable { return new DisposableImpl(fn); } static empty = new DisposableImpl(() => { /* noop */ }); private constructor() {} get closed() { return true; } get isDisposed() { return true; } unsubscribe(): void { /* no op */ } dispose: this['unsubscribe']; }; Disposable.prototype.dispose = function() { this.unsubscribe(); }; export class CompositeDisposable implements ISubscription, Disposable { public closed: boolean; private disposables: ISubscription[]; constructor(...disposables: ISubscription[]) { if (disposables.length > 0 && Array.isArray(disposables[0])) { this.disposables = disposables[0] as any as ISubscription[]; } else { this.disposables = disposables; } } add(v: ISubscription) { if (this.closed) { v.dispose(); } else { this.disposables.push(v); } } remove(v: ISubscription) { const index = this.disposables.indexOf(v); if (index !== -1) { const d = this.disposables.splice(index, 1)[0]; d.dispose(); return true; } return false; } toArray() { return this.disposables.slice(); } get length() { return this.disposables.length; } unsubscribe() { if (this.closed) { return; } this.closed = true; const arr = this.disposables.slice(); this.disposables = []; const length = arr.length; for (let i = 0; i < length; i++) { arr[i].dispose(); } } get isDisposed() { return this.closed; } dispose: this['unsubscribe']; } CompositeDisposable.prototype.dispose = function() { this.unsubscribe(); }; export class SerialDisposable implements ISubscription, Disposable { public closed: boolean = false; private current: ISubscription; unsubscribe() { if (this.closed) { return; } this.closed = true; const current = this.current; this.current = undefined; if (current !== undefined) { current.dispose(); } } getDisposable() { return this.current; } setDisposable(disposable: ISubscription) { if (this.closed) { if (disposable !== undefined) { disposable.dispose(); } } else { const old = this.current; this.current = disposable; if (old !== undefined) { old.dispose(); } } } get isDisposed() { return this.closed; } dispose: this['unsubscribe']; }; SerialDisposable.prototype.dispose = function() { this.unsubscribe(); }; export class SingleAssignmentDisposable implements ISubscription, Disposable { public closed: boolean = false; private disposable: ISubscription; unsubscribe() { if (this.closed) { return; } this.closed = true; const disposable = this.disposable; this.disposable = undefined; if (disposable !== undefined) { disposable.dispose(); } } getDisposable() { return this.disposable; } setDisposable(v: ISubscription) { if (this.disposable !== undefined) { throw new Error(`SerialDisposable already set`); } if (v !== undefined) { if (this.closed) { v.dispose(); } else { this.disposable = v; } } } get isDisposed() { return this.closed; } dispose: this['unsubscribe']; } SingleAssignmentDisposable.prototype.dispose = function() { this.unsubscribe(); }; export class RefCountDisposable implements ISubscription { public closed = false; get isDisposed() { return this.closed; } private count = 0; private primaryDisposed = false; constructor(private subscription: ISubscription) { } unsubscribe() { if (this.primaryDisposed) { return; } this.primaryDisposed = true; this._disposeCheck(); } private _disposeCheck() { if (!this.closed && this.primaryDisposed && this.count === 0) { this.closed = true; const sub = this.subscription; this.subscription = undefined; sub.dispose(); } } getDisposable() { if (this.isDisposed) { return Disposable.empty; } this.count++; return new DisposableImpl(() => { this.count--; this._disposeCheck(); }); } dispose: this['unsubscribe']; } RefCountDisposable.prototype.dispose = function() { this.unsubscribe(); }; export type IDisposable = ISubscription;