How to get current value of RxJS Subject or Observable?
A Subject
or Observable
doesn't have a current value. When a value is emitted, it is passed to subscribers and the Observable
is done with it.
If you want to have a current value, use BehaviorSubject
which is designed for exactly that purpose. BehaviorSubject
keeps the last emitted value and emits it immediately to new subscribers.
It also has a method getValue()
to get the current value.
Simple way to get current value of an Observable (Obtained from a BehaviorSubject)
As far as I can understand your problem I would propably question the usage of a BehaviourSubject
in the first place.
RxJs, as great as it is, is not a fit for every use case and yours could be one of them.
The usage of .value
is an indication for that imo.
Using a simple non Observable variable in the SoundMeterService
that keeps the state would propably resolve all your problems.
If you don't want to do that, my suggestions would be to try something like the following:
There a several places in your flow where you want to check the listeningStatus
and
it may is an option for you to use the tap operator and perform the side effects for all options (not only for 'noResults') in one place?
Example:
export class SoundMeterComponent {
serviceListeningStatus$ = this.sms.listeningStatus.pipe(
tap((status) => {
if (value === 'noResults') {
displayNoResultsMessage();
}
if (value === 'xxx') {
doXXXStuff();
}
})
);
constructor(private sms: SoundMeterService) {}
ngOnInit() {}
}
and the template then subscribes to the serviceListeningStatus$
:
<div *ngIf="(serviceListeningStatus$ | async) === 'noResults' ">
<span>some text</span>
</div>
I think your problem is a great example for an application that wants to do RxJs, because it is great, but due the lack of a full support of reactive approaches in the Angular Framework you can't go fully reactive. I'm thinking of the ngOnInit
or of click events a user makes.
If you want to use RxJs nonetheless it may help to take look at ngx-template-stream or at this great proposal.
Cheers Chris
Get current value from Observable without subscribing (just want value one time)
You need to use BehaviorSubject,
- BehaviorSubject is similar to ReplaySubject except it only remembers the last publication.
- BehaviorSubject also requires you to provide it a default value of T. This means that all subscribers will receive a value immediately
(unless it is already completed).
It will give you the most recent value published by the Observable.
BehaviorSubject provides a getter
property named value
to get the most recent value passed through it.
StackBlitz
- In this example the value 'a' is written to the console:
//Declare a Subject, you'll need to provide a default value.
const subject: BehaviorSubject<string> = new BehaviorSubject("a");
USAGE:
console.log(subject.value); // will print the current value
Conceal the Subject and only expose it's value
In case you want to conceal your BehaviorSubject and only expose it's value, let's say from a Service, you can use a getter like this.
export class YourService {
private subject = new BehaviorSubject('random');
public get subjectValue() {
return this.subject.value;
}
}
Get current value of Subject.asObservable() inside Angular service
Seems you are looking for BehaviorSubject
private _panelOpened = new BehaviorSubject<boolean>(false);
If you subscribe you get the last value as first event.
togglePanel() {
this.currentValue = !this.currentValue;
this._panelOpened.next(this.currentValue);
}
RxJs get value from observable
To get data from an observable, you need to subscribe:
this.singleEvents$.subscribe(event => this.event = event);
In the template you can directly bind to observables using the async pipe:
{{singleEvents$ | async}}
How to get value from Observable
You need to subscribe to the items$
Observable to get the data.
jobsLength() {
this.searchLogic.items$.subscribe((value: any[]) => {
let jobs: any[] = value;
console.log(jobs);
console.log(jobs.length);
});
}
Sample Solution on StackBlitz
References
Observable (Subscribing)
take(1) vs firstValueFrom vs observable.value
Basically using take(1)
or firstValueFrom
is the same because they access the value asynchronously:
myStore$.pipe(
take(1)
).subscribe(value => {...});
firstValueFrom
turns Observable into a Promise so you can use async
/await
:
const value = await firstValueFrom(myStore$.pipe(
take(1)
));
Using BehaviorSubject.value
to synchronously access its value is in general not recommended. It might behave unexpectedly if BehaviorSubject
errors or when it's unsubscribed:
import { BehaviorSubject } from 'rxjs';
const subject1 = new BehaviorSubject(1);
console.log(subject1.value);
subject1.error(new Error('broken'));
try {
console.log(subject1.value);
} catch (e) {
console.error(e);
}
const subject2 = new BehaviorSubject(2);
console.log(subject2.value);
subject2.unsubscribe();
try {
console.log(subject2.value);
} catch (e) {
console.error(e);
}
Live demo: https://stackblitz.com/edit/rxjs-npalak?devtoolsheight=60
Related Topics
Difference Between Knockout View Models Declared as Object Literals VS Functions
Get Hours Difference Between Two Dates in Moment Js
How to Load Data from a CSV File in D3 V5
Finding Matches Between Multiple JavaScript Arrays
How to Detect Whether an Iframe Is Loaded
Sharing a Variable Between Multiple HTML Pages
Load HTML File Contents to Div [Without the Use of Iframes]
How to Exchange Variables Between Two HTML Pages
JavaScript Localstorage Object Broken in Ie11 on Windows 7
How to Get Current Value of Rxjs Subject or Observable
Remove All Elements Contained in Another Array
Why Does JavaScript Object Show Different Values in Console in Chrome, Firefox, Safari
Are All JavaScript Callbacks Asynchronous? If Not, How to Know Which Are
Getattribute() Versus Element Object Properties
Getelementsbyname() Not Working
How to Read Xml File Contents in Jquery and Display in HTML Elements