UNPKG

@towns-protocol/sdk

Version:

For more details, visit the following resources:

109 lines 3.51 kB
export class Observable { _nextId = 0; subscribers = []; _value; _dispose; constructor(value) { this._value = value; } get value() { return this._value; } set(fn) { return this.setValue(fn(this.value)); } setValue(newValue) { if (this._value === newValue) { return false; } const prevValue = this._value; this._value = newValue; this.notify(prevValue); return true; } subscribe(subscriber, opts = {}) { const nextId = this._nextId++; const sub = { id: nextId, fn: subscriber, once: opts?.once ?? false, condition: opts?.condition ?? (() => true), }; this.subscribers.push(sub); if (opts.fireImediately) { this._notify(sub, this.value, this.value); } return () => this.unsubscribe(subscriber); } when(condition, opts = { timeoutMs: 5000 }) { const logId = opts.description ? ` ${opts.description}` : ''; const timeoutError = new Error(`Timeout waiting for condition${logId}`); return new Promise((resolve, reject) => { const timeoutHandle = setTimeout(() => { reject(timeoutError); }, opts.timeoutMs); this.subscribe((value) => { clearTimeout(timeoutHandle); resolve(value); }, { fireImediately: true, condition: condition, once: true }); }); } unsubscribe(subscriber) { this.subscribers = this.subscribers.filter((sub) => { if (sub.fn === subscriber) { return false; } return true; }); } // T is the observable’s element type, U is the mapped element type map(fn) { const mappedObservable = new Observable(fn(this.value, this.value)); mappedObservable._dispose = this.subscribe((newValue, prevValue) => { mappedObservable.setValue(fn(newValue, prevValue, mappedObservable.value)); }); return mappedObservable; } throttle(ms) { const throttledObservable = new Observable(this.value); let timeoutId = null; let pendingValue = null; const unsubscriber = this.subscribe((newValue) => { pendingValue = newValue; if (timeoutId === null) { timeoutId = setTimeout(() => { if (pendingValue !== null) { throttledObservable.setValue(pendingValue); pendingValue = null; } timeoutId = null; }, ms); } }); throttledObservable._dispose = () => { if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; } unsubscriber(); }; return throttledObservable; } dispose() { this.subscribers = []; this._dispose?.(); } notify(prevValue) { const subscriptions = this.subscribers; subscriptions.forEach((sub) => this._notify(sub, this.value, prevValue)); } _notify(sub, value, prevValue) { if (sub.condition(value)) { sub.fn(value, prevValue); if (sub.once) { this.subscribers = this.subscribers.filter((s) => s !== sub); } } } } //# sourceMappingURL=observable.js.map