Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - subscribe multiple times without firing multiple calls?

Tags:

angular

rxjs

I have a service call, whose response is cached inside my Angular service like this:

public cacheMyServiceResponse(): Observable<any> {
  return this.appConfig.getEndpoint('myService')
    .pipe(
      switchMap((endpoint: Endpoint) => this.http.get(endpoint.toUrl())),
      tap((body: any) => {
        if (body) { //  this endpoint can also return a 204 (No Content), where body is null
          this.cache = body.myData;
        }
      }),
      take(1),
      catchError(error => {
        this.errorService.trackError(error.status);
        return of(true);
      })
    );
}

So the response of my http.get call will be cached here, in a global variable called "cache".

The problem is, this call may really response very late, so we wanted to call this endpoint as soon as our page loads (while initialization). But the actual response, or whether our call is finished (either success or error), we need this info only then when user clicks a button.. Of course at that moment of button click, the response may not be there yet, and in this case i would like to wait for it. (so i need more than a simple boolean flag)

So i want to initialize this call in a ngOnInit like this:

ngOnInit() {
    this.myService.cacheMyServiceResponse().subscribe();
}

But somewhere else i need to know if it is already finished the call, without firing my http call twice.

onClick() {
    this.myService.cacheMyServiceResponse().subscribe(() => {
       // call is finished..
    });
}

At the moment the service will be called twice. How can i do this?

PS: i dont have an error handling on purpose, i just have to know if the service call finished at all.

like image 739
akcasoy Avatar asked Oct 25 '25 04:10

akcasoy


1 Answers

I suggest to use ReplaySubject() and subscribe to the ReplaySubject() onClick instead, it will wait for your service to emit data while it still can be subscribed to, also if it did not be subscribed before the data from service emit, you wont miss the data:

yourWaitingData = new ReplaySubject();
subscription;

ngOnInit() {
    this.myService.cacheMyServiceResponse().subscribe(res => {
        //yourWaitingData only emit when res is return from API call
        this.yourWaitingData.next(res)
    });
}

Then subscribe to it:

onClick() {
    if(this.subscription){
       this.subscription.unsubscribe()
    }
    this.subscription = this.yourWaitingData.subscribe((x) => {
       // subscribed and will wait for data to be emited from service
       console.log(x)
    });
}
like image 58
Ethan Vu Avatar answered Oct 27 '25 18:10

Ethan Vu