Search code examples
javascriptreactjsangularrxjsbehaviorsubject

Should I use asObservable in BehaviorSubject?


I am wondering what is the two approach in the following code in BehaviorSubject.

As far as I know:

The asObservable method not only cast it to an Observable, it also removes the Observer implementation. Therefore you are not able to call next, error & complete on the instance returned by asObservable().

but the following also makes me confused:

By only exposing asObservable you can consume the values emitted but prevent from making changes to the BehaviorSubject from outside the service where this BehaviorSubject was created. For this reason use asObservable().

Is there anything wrong with these definitions?

export class DataService {

    // usage I : using getter
    private messageSubject = new BehaviorSubject<any>(undefined);

    getMessage(): BehaviorSubject<any> {
        return this.messageSubject;
    }

    setMessage(param: any): void {
        this.messageSubject.next(param);
    }


    // usage II : using asObservable()
    private messageSubject = new BehaviorSubject<any>(undefined);
    
    currentMessage = this.messageSubject.asObservable();

    setMessage(param: any) {
    this.messageSubject.next(param)
    }
}

Which approach above is better to use or what is the pros and cons for these 2 approaches?

Update: Last time I finalised the correct usage as the following:

// usage III : using @martin's approach:
private messageSubject = new BehaviorSubject<any>(undefined);
    
public messages$: Observable<any> = this.messageSubject;

//should I set the observable still using the following method without any changing? Or do I need an update?
setMessage(param: any) {
    this.messageSubject.next(param)
}

Solution

  • Actually, the recommended way of doing this in TypeScript is only by type casting like this:

    private messageSubject = new BehaviorSubject<any>(undefined);
    
    public messages$: Observable<any> = this.messageSubject;
    

    This way it's TypeScript compiler who won't let you call next(), error() or complete(). Using asObservable() is recommened only when using RxJS in pure JavaScript. For example, internally in RxJS source code it never uses asObservable() even though it uses and exposes Subjects => Observables a lot.

    For more info see discussion: https://github.com/ReactiveX/rxjs/pull/2408