ram12393
ram12393

Reputation: 1258

How to prevent calling same api in different components

I have a doctor's service and it has API call like below

patientDetails():Observable<any>
 {
   return http.get("/home/patient-details")
 }

the above service I'm subscribing the in different module components to get the patient details. Here I'm thinking how to prevent duplicate API calling in multiple components?

Is there any option to call the API only once and share the data among the project

Upvotes: 0

Views: 1638

Answers (3)

Superman.Lopez
Superman.Lopez

Reputation: 1600

I believe that the answers Bardr and that_guy provided both require the API call to take place on the initiating of the service (as these are called in the constructor).

I wanted to have a non-repeating API call for multiple components, but only if any of the component needed that call. So it couldn't depend on the constructor. I decided to implement it in the following way, where a backing observable is checked for value, and only if the backing observable has a value of null is the API called. It might be possible to combine this pattern with the above answers.

in my service:

private foobarReference = new BehaviorSubject<FoobarReference>(null);
public foobarReference$ = this.foobarReference.asObservable();
public getFoobarReferences(): Observable<FoobarReference> {
    if (this.foobarReference.getValue() == null) {
        this.httpClient.get<FoobarReference>('/api/references/foobar/').subscribe(data => this.foobarReference.next(data));
    }
    return this.foobarReference$;
}

In my components I subscribe to it like any other observable (I use takewhile as the observable doesn't change value during the life of the service):

private this.foobarReferences: FoobarReference;
this.foobarService.getFoobarReferences().pipe(takeWhile(x => x == null, true)).subscribe(data => this.foobarReferences = data);

Upvotes: 0

Bardr
Bardr

Reputation: 2559

HttpClient's methods return Cold Observable. To achive functionality you want, you would need Hot Observable. You can convert Cold Observable to Hot Observable (also called Warm Observable because of warming it) using shareReplay(numberOfEventsToShare) and store it in property. To understand why you need this operator you need to know what means that Observable is Hot or Cold. Check out this great article.

But in short for your case: Hot Observable shares one producer which can produce values even before someone will subscribe to him. On the flip side Cold Observable creates producer for each observer (meaning that state is not shared among different observers).

So shareReplay(1) operator will make observable returned by HttpClient warm by sharing source and replaying 1 event for all observers (for future ones also).

I created a StackBlitz demo where you can see that there is no subsequent HTTP requests even after adding new components.

Upvotes: 2

that_guy
that_guy

Reputation: 2445

public patientDetails$: Observable<any>;

constructor(...) {
    this.patientDetails$ = http.get("/home/patient-details").pipe(shareReplay(1));
}

Upvotes: 0

Related Questions