Observable.ts
93 lines
| 2.2 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r14 | import { IObservable, IDestroyable, ICancellation } from '../interfaces'; | |
|
|
r13 | import { Cancellation } from '../Cancellation' | |
| import { argumentNotNull } from '../safe'; | |||
|
|
r14 | interface Handler<T> { | |
| (x:T) : void | |||
| } | |||
|
|
r13 | ||
|
|
r14 | interface Initializer<T> { | |
| (notify: Handler<T>) : (() => void) | void; | |||
| } | |||
|
|
r13 | ||
|
|
r14 | class Observable<T> implements IObservable<T>, IDestroyable { | |
| private _once = new Array<Handler<T>>(); | |||
| private readonly _observers = new Array<Handler<T>>(); | |||
|
|
r13 | ||
|
|
r14 | private readonly _cleanup : (() => void) | void; | |
| constructor(func?: Initializer<T>) { | |||
| this._cleanup = func && func(this._notify.bind(this)); | |||
|
|
r13 | } | |
|
|
r14 | on(observer: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable { | |
|
|
r13 | argumentNotNull(observer, "observer"); | |
| this._observers.push(observer); | |||
| let me = this; | |||
| return { | |||
| destroy() { | |||
| me._removeObserver(observer); | |||
| } | |||
| } | |||
| } | |||
|
|
r14 | next(ct: ICancellation = Cancellation.none): Promise<T> { | |
|
|
r13 | return new Promise<T>((resolve, reject) => { | |
| this._once.push(resolve); | |||
| if (ct.isSupported()) { | |||
| ct.register((e) => { | |||
| this._removeOnce(resolve); | |||
| reject(e); | |||
| }); | |||
| } | |||
| }); | |||
| } | |||
|
|
r14 | destroy() { | |
| if(this._cleanup) | |||
| this._cleanup.call(null); | |||
|
|
r13 | } | |
|
|
r14 | protected onObserverException(e: any) { | |
| } | |||
| private _removeOnce(d: Handler<T>) { | |||
|
|
r13 | let i = this._once.indexOf(d); | |
| if (i >= 0) | |||
| this._once.splice(i); | |||
| } | |||
|
|
r14 | private _removeObserver(d: Handler<T>) { | |
|
|
r13 | let i = this._observers.indexOf(d); | |
| if (i >= 0) | |||
| this._observers.splice(i); | |||
| } | |||
|
|
r14 | protected _notify(evt: T) { | |
| let guard = (observer: Handler<T>) => { | |||
|
|
r13 | try { | |
| observer(evt); | |||
| } catch (e) { | |||
| this.onObserverException(e); | |||
| } | |||
| } | |||
| if (this._once.length) { | |||
| for (let i = 0; i < this._once.length; i++) | |||
| guard(this._once[i]); | |||
| this._once = []; | |||
| } | |||
| for (let i = 0; i < this._observers.length; i++) | |||
| guard(this._observers[i]); | |||
| } | |||
| } | |||
| namespace Observable { | |||
| } | |||
| export = Observable; |
