I have a service \"MyHttpService\" that includes an observable like this:
grabData() {
return this.http.get(\'myaddress\')
.map((res
The Http
service returns what are known as cold observables. This means that every new subscriber will cause the work for that observable to be done again, which in the case of Http
, is to make the network request.
Luckily, there are mechanisms in RxJS to allow you to publish (a.k.a multicast or multiplex) an observable so that multiple subscribers do not cause multiple requests.
The way I usually do this for Http
is with the .publishReplay(1).refCount()
pair of operators. The .publishReplay(1)
means that later subscribers get the most recent successful value straight away, without making another request. .refCount()
means that the first subscriber makes the request, and the last one to unsubscribe cleans up the original Http
observable.
Version 5.4.0 added a shortcut for these two operators, which is .shareReplay(1)
.
Just whack either version on the end of the line in your grabData()
service method, and it should work like you desire.
grabData() {
return this.http.get('myaddress')
.map((res:Response) => {return res.json()})
.catch((error:any) =>
Observable.throw(error.json().error || 'Server error'))
.publishReplay(1).refCount(); // or .shareReplay(1)
}
You can use the share operator to make an observable multicast. This is also relevant within a single component as multiple async bindings to the same osbervable will cause multiple requests to be made. There is a good ng-conf talk here that covers the issue.
import 'rxjs/add/operator/share';
grabData() {
return this.http.get('myaddress')
.map((res:Response) => {return res.json()})
.catch((error:any) => Observable.throw(error.json().error || 'Server error'))
.share();
}
When you subscribe in TwoComponent it will cause the http request to be sent again. The best way for you to prevent multiple http calls would be to store the response data in your service and before the http call, check if you have already saved the data and if so just directly returning the data.