RxJs get value from observable
Asked Answered
V

6

61

In component :

singleEvent$: Observable<Event>;

On init, I get observable

this.singleEvent$ = this._eventService.events$
  .map(function (events) {
    let eventObject = events.find(item => item.id === eventid);
    let eventClass: Event = new Event(eventObject);
    return eventClass;
  });

How can I take current value like event.name ?

Vaden answered 3/6, 2016 at 6:22 Comment(1)
Please add more code to the question. A plunk would also do.Overdye
E
104

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}}
Eurythermal answered 3/6, 2016 at 7:12 Comment(5)
My subscriber in service But i need take name in componentVaden
Sorry, I can't make any sense from your comment.Spineless
I think he means that in the service he uses .subscribe and then have a subject (or similar) that the component uses. let´s say that there is a page component that have a child that takes an async input. then the parent component needs some data for other requests?Video
@Video sorry, but that doesn't make it more clear. If this is actually a question that bothers you, then I'd suggest to create a new question that includes the code that demonstrates what you try to accomplish.Spineless
I believe what he is missing is that he needs to use .subscribe in the component as well. :)Video
C
16

To add on to Günter Zöbauer's answer, a BehaviorSubject may be what you are looking for if you're looking to synchronously get the value inside of your Observable.

A BehaviorSubject is an Observable that always has a value, and you can call myBehaviorSubject.getValue() or myBehaviorSubject.value to synchronously retrieve the value the BehaviorSubject currently holds.

Since it is itself an observable as well, you can still subscribe to the BehaviorSubject to asynchronously react to changes in the value that it holds (e.g. myBehaviorSubject.subscribe(event => { this.event = event })) and use the async pipe in your component's template (e.g. {{ myBehaviorSubject | async }}).

Here's some usage to match your given example to create a BehaviorSubject in your component from the given service:

@Component({
  //...
})
export class YourComponent implements OnInit {
  singleEvent$: BehaviorSubject<Event>;

  constructor(private eventService: EventService){}

  ngOnInit(){
    const eventid = 'id'; // <-- actual id could go here
    this.eventService.events$
      .pipe(
        map(events => {
          let eventObject = events.find(item => item.id === eventid);
          let eventClass: Event = new Event(eventObject);
          return eventClass;
        })
      )
      .subscribe(event => {
        if(!this.singleEvent$){
          this.singleEvent$ = new BehaviorSubject(event);
        } else {
          this.singleEvent$.next(event);
        }
      });
  }
}
Calculable answered 27/5, 2018 at 15:26 Comment(4)
What I want is an observable that I can observe without subscribing, and without using BehaviorSubject, since you can modify it with next()Tail
recently been really liking the async/await API for similar use-cases that might be of interest @Narvalex. The idea is you use it like so: const foo = await obs$.pipe(take(1)).toPromise() inside of an asynchronous function.Calculable
Thanks for the tip men. This was indeed an interview question about the difference between a Subject and BehaviourSubject and it is all clear to me now.Entablement
Isn't it risky to expose BehaviorSubject on your components?! What's the point of using Observable (cloning) if you are just exposing the BehaviorSubject?Astronaut
B
10

You can use observable.pipe(take(1)).subscribe to limit the observable to get only one value and stop listening for more.

let firstName: string; 

        this.insureFirstName
            .pipe(take(1))  //this will limit the observable to only one value
            .subscribe((firstName: string) => {
                this.firstName = firstName; asssgning value 
            });
        console.log(this.firstName); //accessing the value
Bussy answered 6/5, 2020 at 13:49 Comment(0)
B
1

If you need the value of an observable at a specific point in time I would convert it to a Promise and await for it like so:

import { firstValueFrom } from 'rxjs';

const value = await firstValueFrom(obs$);

The Observable would resolve immediately if it is an BehaviorSubject under the hood.

Bobbiebobbin answered 14/4, 2023 at 15:11 Comment(0)
H
0

Adding to what @ZackDeRose was adding on @Günter Zöchbauer response

private beneficiary = new BehaviorSubject<__IBeneficiary>(newBeneficiary);
beneficiary$ = this.beneficiary.asObservable();

setBeneficiaryInfo(beneficiary: __IBeneficiary): void {
    this.beneficiary.next(beneficiary);
    // when your you subscribe to beneficiary$ you would get the new value
}

/* when implementing in component or other function
   this.beneficiary$.subscribe(
        item => {
            // use current value
        }
    );
*/

modePersonalInformation(personalInfo, mode: string): Observable<any> {
    const $beneficiary = this.beneficiary.value; 
    // this will get the current observable value without the subscrib callback function
    return this.http.post<any>(
        `${this.apiURL}/${mode}-biography/personal` + ((mode === 'update' && $beneficiary?.id) ? `/${$beneficiary.id}` : ''),
        {...personalInfo},
        this.httpOptions
    )
}

you would have to put some conditionals to check if you want to use an existing object or not

Housemaid answered 26/7, 2021 at 9:57 Comment(0)
E
0

I hate to say it, but these are all wrong answers. You can easily get the value if it exists by using,

this._eventService.events$.source['_value'] 

And get any value you want from the object. The source is deprecated but still works.

Exiguous answered 28/1, 2023 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.