Using shareReplay(1) in Angular - still invokes http request?

27,438

Solution 1

If you call every time this.http.get(API_ENDPOINT).pipe(shareReplay(1)), each time http request will be triggered. If you want to make http call once and cache data, the following is recommended.

You first get the observable for data:

 ngOninit(){
    this.data$ =  this._jokeService.getData().pipe(shareReplay(1));
    }

Now subscribe multiple times:

 public getData(){
     this.data$.subscribe();
    }

Your service:

public getData() {
    return this.http.get(API_ENDPOINT)
  }

Solution 2

In service:

getData$ = this.http.get(API_ENDPOINT).pipe(shareReplay(1));

In component, need to unsubscribe and you can subscribe multiple times with single API call:

ngOninit(){
   this.data$ =  this._jokeService.getData$;
   this.data$.subscribe() 
}

In template, use:

*ngIf="data$ | async as data"
Share:
27,438

Related videos on Youtube

Royi Namir
Author by

Royi Namir

Updated on October 29, 2020

Comments

  • Royi Namir
    Royi Namir over 3 years

    I've created a demo (ng-run) where I have a button which invokes an Http request.

    When the button is clicked, I invoke this method :

    public getData(){
     this._jokeService.getData().subscribe();
    }
    

    Which in turn invokes this ( from a service) :

     public getData() {
        return this.http.get(API_ENDPOINT).pipe(shareReplay(1))
      }
    

    The problem is that on every click - I still see a new http request initiated :

    enter image description here

    Question:

    Why doesn't shareReplay keeps the last value of the response?
    How can I make my code to invoke the http only once and keep that value for future subscriptions ?

    Edit: solution is here

    • jonrsharpe
      jonrsharpe almost 6 years
      Why wouldn't you see a new request? You're calling http.get again! The shareReplay prevents additional subscribers to the returned observable triggering a new response, but you're creating a new one each time. If you want to make a single request then expose the existing value to future subscribers use a ReplaySubject as I show here: stackoverflow.com/a/41554338/3001761. Then you can differentiate between triggering a new request and asking for the existing value, plus if you do need to make an additional request all existing subscribers receive the new result when available.
    • Royi Namir
      Royi Namir almost 6 years
      I don't think I need to create a middle ReplaySubject just to keep those values. IMHO - it can be done without it.
    • jonrsharpe
      jonrsharpe almost 6 years
      Yes, it can be done without it, as long as you only ever want one value back. But you'll still need to store and expose a single observable, not create a new one each time.
    • Royi Namir
      Royi Namir almost 6 years
      Yeah silly mistake of mine . I've created each time a new observable ( happens)
    • Adrian Brand
      Adrian Brand over 4 years
      I have written a library ngx-RxCache github.com/adriandavidbrand/ngx-rxcache to help you manage thing like this in Angular. Have a read about it here medium.com/@adrianbrand/…
  • Royi Namir
    Royi Namir almost 6 years
    Yeah , I've created a new observable each time..... that was my mistake. Tnx.). It's been a long day...
  • lolplayer101
    lolplayer101 over 4 years
    @siva636 I understand what you are doing here but can you tell me the benefits of your approach over simply piping the http.get in your service and extracting the data and putting it in a non observable variable in the service?