@ces/observable-state
Version:
A type of Observable that holds state that can be consumed synchronically / imperatively.
48 lines (47 loc) • 2 kB
JavaScript
import { Observable } from 'rxjs';
// This class is used to turn an Observable into something quite like a BehaviorSubject, with
// the exceptions that it can be directly created from an Observable and it doesn't expose an
// observer interface.
//
// Its intended purpose is to turn BehaviorSubjects or other Observable subtypes that emit
// synchronously back into something that can be read imperatively / synchronously after
// they have been piped and thus become regular Observables, losing their ability to be
// consumed imperatively / synchronously.
export class ObservableState extends Observable {
constructor(o, owner) {
super((subscriber) => o.subscribe(subscriber));
this.owner = owner;
this.getValue = () => this.value;
this.innerSubscription = this.subscribe(value => this.value = value);
}
static from(observable, owner) {
return new ObservableState(observable, owner);
}
static release(owner) {
if (ObservableState.instances.has(owner)) {
const ownerSet = ObservableState.instances.get(owner);
const ownerArray = Array.from(ownerSet);
for (const instance of ownerArray)
instance.release();
}
}
static track(instance, owner) {
if (!ObservableState.instances.has(owner))
ObservableState.instances.set(owner, new Set());
ObservableState.instances.get(owner).add(instance);
}
static untrack(instance, owner) {
if (ObservableState.instances.has(owner)) {
const ownerSet = ObservableState.instances.get(owner);
ownerSet.delete(instance);
if (!ownerSet.size)
ObservableState.instances.delete(owner);
}
}
release() {
this.innerSubscription.unsubscribe();
ObservableState.untrack(this, this.owner);
}
}
ObservableState.instances = new Map();
export const os = (observable, owner) => ObservableState.from(observable, owner);