This question looks long, but it should be a very basic rxjs question. Please help if you can.
I'm writing an Angular 7 app, with a service, component and a template as follows, and I want to access the last value of the observable in an easy way.
SoundMeterService
In the service, I have a private BehaviorSubject which I use to emit values using 'next'.
I expose this BehaviorSubject to consumers using .asObservable() in order to prevent consumers from doing .next() and emit new values.
In the service, I access the current value of listeningStatusSubject
using .value.
export type SoundMeterStatus = 'noResults' | 'isRunning' | 'hasResults';
export class SoundMeterService {
private listeningStatusSubject: BehaviorSubject<SoundMeterStatus> = new BehaviorSubject<SoundMeterStatus>('noResults');
get listeningStatus() { return this.listeningStatusSubject.asObservable(); }
// somewhere in the code I emit a different value
someFunc() {
if (this.listeningStatusSubject.value === 'noResults' )
this.listeningStatusSubject.next('isRunning');
}
}
SoundMeterComponent
Following best practices with observables, in the component, I'm using direct access to the service's Observable (via listeningStatus
getter) so that it is automatically subscribed to and unsubscribed in the template (see below).
export class SoundMeterComponent {
serviceListeningStatus$ = this.sms.listeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
// I want to check the value of listeningStatus in a simple way without pulling the value out and saving it locally in SoundMeterComponent
}
}
SoundMeterTemplate
I'm using Angular's async pipe so that it automatically subscribes and unsubscribes to the observable when the component is destroyed (to avoid manual subscriptions as mentioned here)
<div *ngIf="(serviceListeningStatus | async) === 'noResults' ">
<span>some text</span>
</div>
My question
This approach works perfectly. But I want to check the value of listeningStatus
in a simple way inside ngOnInit() without pulling the value out and saving it locally in SoundMeterComponent, and without exposing the BehaviorSubject listeningStatusSubject
itself to check its value using .value, as described below:
1) Pulling the value from the service and saving it locally in SoundMeterComponent:
SoundMeterComponent
export class SoundMeterComponent {
serviceListeningStatus$ = this.sms.listeningStatus;
private serviceListeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
// Pulling the value from the service:
this.sms.listeningStatus.subscribe( status => this.serviceListeningStatus = status ); // I'm trying to avoid this
if (this.serviceListeningStatus === 'noResults' ) {
displayNoResultsMessage();
}
}
}
2) exposing the BehaviorSubject itself and check its value using .value like this:
SoundMeterService
export class SoundMeterService {
private listeningStatus: BehaviorSubject<SoundMeterStatus> = new BehaviorSubject<SoundMeterStatus>('noResults');
get listeningStatus() { return this.listeningStatus; }
}
SoundMeterComponent
export class SoundMeterComponent {
serviceListeningStatus = this.sms.listeningStatus;
constructor(
private sms: SoundMeterService
) {}
ngOnInit() {
if (this.sms.listeningStatus === 'noResults' ) {
displayNoResultsMessage();
}
}
}
SoundMeterTemplate
<div *ngIf="(serviceListeningStatus.asObservable() | async) === 'noResults' ">
<span>some text</span>
</div>
Please help me understand which approach is better while keeping clean and simple code. I know there are many questions on how to get the value from a BehaviorSubject like Simple way to get the current value of a BehaviorSubject with rxjs5 or How to get current value of RxJS Subject or Observable? , but please note that this is a different question. Thanks!