1
votes

I'm new in Angular and Observables. My problem is: in my component HomePage I call service that call http.get and return an observable. On my template HomePage I use async for this data$. I need to call another void function in ngOnInit that will use data$ when it is returned. So I can not to figured it out how to do this.

HomePage.ts

export class HomePage implements OnInit {

  data$: Observable<any>;

  ngOnInit(): void {
    //I need userId that will be returned here
    this.data$ = this.dataService.getMyData(); 
    //how to call this function after data$ is returned?
    this.sendMessage(data.userId);
  }

  sendMessage(data.userId){
     //send this userId 
  }
}

HomePage.html

<app-homepage form="true" *ngIf="{ data: data$ | async} as myData">
<div *ngIf="data.userId">
///....

I've tried this: but each time I input some data on the page - it calls sendMessage() multiple times...

this.data$ = this.dataService.getMyData().pipe(
      tap((data) => {
        this.sendMessage(data.userId);
        console.log("in pipe")//here I see multiple calls when I click on checkbox for exemple..
      }));
3

3 Answers

0
votes

Try

this.data$ = this.dataService.getMyData().pipe(
  take(1),
  tap((data) => {
    this.sendMessage(data.userId);
    console.log("in pipe")//here I see multiple calls when I click on checkbox for exemple..  
  }
));
0
votes

If your service is returning an Observable, then you need to subscribe to it in order to read what the response is, like this:

export class HomePage implements OnInit {

  // data$: Observable<any>;
  theResult: any;

  ngOnInit(): void {    
    this.dataService.getMyData().subscribe((response) => {
      console.log('See your response', response);
      theResult = response.userId;
      this.sendMessage(theResult);
    });
  }

  sendMessage(data.userId){
     //send this userId 
  }
}

Keep in mind that, when you subscribe to an Observable, that is an asynchronous operation, that is why, after you get the response in the subscribe step, you will need to call your other function.

-1
votes

Using the tap operator is the appropriate way to run side effects when a value is emitted through the stream.

If you want to prevent multiple subscriptions from triggering the side effect logic, you can use the shareReplay operator to prevent this behavior:

this.data$ = this.dataService.getMyData().pipe(
    tap(data => this.sendMessage(data.userId)),
    shareReplay()
);

Here's a StackBlitz sample

each time I input some data on the page - it calls sendMessage() multiple times

If interacting with the page is causing the call to be executed multiple times, change detection may be somehow causing this. You may need to share more code to figure out why that would be.