Reputation: 181
I have a question regarding observables.
Lets say I have a Service with an observable and I have two different components that subscribe to that observable. The Observable itself does a Backend query.
Currently I have a problem, that with the same input both of the observables in the separate components send out independent network requests with the same input param.
Is there way to make it so, that if these 2 observable called are made when one of them is executing, the second one will wait for the first to finish and use that result?
I am using httpClient and angular 5 at the moment
Any suggestions or design patterns are welcome :)
Upvotes: 0
Views: 1954
Reputation: 181
I would like to thanks all of the suggested answers, as they guided me towards lookin at RXJS documentation a little bit deeper.
So what I found and what others basically said here before, the observable was cold. So what that means is that every time the observable is subscribed to a new request is sent.
To make it hot, so subscribers would wait for the response I used the share() operator from RxJS.
Please more detailed use cases and explanations from the following blog posts:
https://blog.strongbrew.io/how-share()-can-reduce-network-requests/ and https://blog.novanet.no/angular-pitfall-multiple-http-requests-with-rxjs-and-observable-async/
Thanks again to Vikas and Rakesh for pointing me in the right direction :)
Upvotes: 0
Reputation: 12036
This is actually the normal behavior of the HTTP
observables as they are Cold.
When a cold observable
has multiple subscribers
, the whole data stream is re-emitted for each subscriber
. Each subscriber becomes independent and gets its own stream of data
To Avoid Duplication of HTTP Requests you can use shareReplay
operator.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {Observable} from 'rxjs';
import {shareReplay,tap}from 'rxjs/operators';
@Injectable()
export class ShareService {
public response$:Observable<any>;
constructor(private httpc:HttpClient)
{
this.sendRequest();
}
public sendRequest()
{
this.response$= this.httpc.get('url').
pipe(tap(res=>{console.log('called');return res;}),shareReplay(1))
}
fetchData()
{
return this.response$;
}
}
component1:
constructor(service:ShareService)
{
service.fetchData().subscribe(result=>{
console.log(result);
})
component2:
constructor(service:ShareService)
{
service.fetchData().subscribe(result=>{
console.log(result);
})
Upvotes: 1
Reputation: 272
Please use service as a singleton. This can be done by configuring service in provider list in the root module.
In the service, have an observable as a variable.
Call the same service method from both components.
The service method should check if observable variable is already set. If set, return the variable. If not set, call the httpclient function and assign results to the observable variable, and return the same.
I hope this logic should work.
Upvotes: 1