RxJS: Making simple variable as Observable

9/21/2017 by Yuriy Frankiv

It is hard to build application with Angular without taking advantage of Observables. There is a bunch examples of handling http requests using them in the web.

Sometimes we need to use them to handle simple values. In the case it is usually implemented in a service. Service has to provide Observable reference so components can subscribe for the updates. It requires at least two members declared in the service: Subject & Observable. Having half dozen observables in the service produces a dozen of declaration and makes code cluttered. Implementation:

import { Observable, ReplaySubject, Subject } from "rxjs";

export class Subscribable<T> {

    private valueSource: Subject<T> = new ReplaySubject<T>(1);
    public value: Observable<T>;
    private _value: T;

    constructor() {
        this.value = this.valueSource.asObservable();
    }

    public set(val: T) {
        this.valueSource.next(val);
        this._value = val;
    }

    public get(): T {
        return this._value;
    }
}

It uses ReplaySubject to re-play only last change to the subscriber. There couple benefits of using this class:

Les code: only one member is declared in the class
Type control: ensures that only type from generic will be delivered to subscriber
Encapsulation: implementation is hidden, so you can experiment with different type of subjects or another notification mechanism

Usage:

Subscribable<> should be declared in the service:

public isFullScreen: Subscribable<boolean> = new Subscribable<boolean>();

…
public setFullscreen(value: boolean) {
	this.set(value);
}

Value change can be handled in component:

this.service.isFullScreen.value.subscribe(res => { /*handle fullscreen*/ });

What else to consider:

In case last value should be “re - send” to observers:

public notify() {
    this.valueSource.next(this._value);
}

To send an error:

public error(message: any) {
    this.valueSource.error(message);
}