Using shareReplay(1) in Angular - still invokes http request?
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"
Related videos on Youtube
Royi Namir
Updated on October 29, 2020Comments
-
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 :
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 almost 6 yearsWhy wouldn't you see a new request? You're calling
http.get
again! TheshareReplay
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 aReplaySubject
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 almost 6 yearsI don't think I need to create a middle
ReplaySubject
just to keep those values. IMHO - it can be done without it. -
jonrsharpe almost 6 yearsYes, 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 almost 6 yearsYeah silly mistake of mine . I've created each time a new observable ( happens)
-
Adrian Brand over 4 yearsI 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 almost 6 yearsYeah , I've created a new observable each time..... that was my mistake. Tnx.). It's been a long day...
-
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?