dragonfly
dragonfly

Reputation: 17773

Observable returned by Http fired each time async pipe is subscribing

So I have this method that returns some observable.

fetch(publication: Publication): Observable<Array<ProcessingCenter>> {
  return this.http.get(`${BASE_URL}/api/publications/${publication.id}`, {
    headers: headers
  }).map(response => {
    return response.json() as Array<ProcessingCenter>;
  })
}

I store returned value (getObservable always returns the same observable).

And in one component I utilize this observable in component:

<tr *ngFor="let pc of getObservable(p) | async">
  ...
</tr>

And now, even though I'm always using the same observable, when I toggle component, each time it is created and async pipe is subscribing, an AJAX request is issued. AFAIK AJAX request should be issued only once, when first subscription is done, right?

EDIT

Thanks for answers, but they just don't focus on the real issue. Let's me rephrase it.

  1. Suppose I have a observable variable myObservable returned by Http service

  2. Suppose in template I'm using this variable with async pipe

  3. Suppose that I'm toggling a part of the template that is using async pipe with simple *ngIf

E.g.:

<button (click)="toggle = !toggle">Toggle</button>
<table class="table table-condensed" *ngIf="toggle">
  <!-- Somewhere in here is myObservable | async  -->>
</table>

Now, when I click the button, each time table is toggled, http request is sent (even though myObservable is still the same observable object (component's instance field).

And the questions is: what is so special about async pipe or observable that is returned by Http service that makes them do Http request each time a subscription is made?

Upvotes: 0

Views: 2377

Answers (3)

Akshay Vijay Jain
Akshay Vijay Jain

Reputation: 15935

You do not need to worry about it because, browser understands that you are requesting same resource again, which is already present in cache, so browser add header in request stating, give me content only if its new, So although request is made each time, you get data from server only if its new, otherwise you just get empty response with 304 status.

This repeated request also can be avoided with proper configurations on backend, which states for how much time browser can consider the response to be new by default.

This link explains it https://www.linkedin.com/pulse/worried-making-repeated-requests-same-resource-slowing-akshay-jain/

Upvotes: -3

Federico Galassi
Federico Galassi

Reputation: 682

That's the normal way observables work. The logic they run in order to produce values (ie firing an http request and waiting for its result) is executed every time an observer subscribes. These are called cold observables. You can instead have hot observables that execute the logic once, by using publish(). If an observer subscribed after such observable emitted its values, it would receive nothing. But you can have other variants of hot observables that would know how to deal with already emitted values, at each new subscription. See publishLast(), publishBehavior() and publishReplay().

Upvotes: 3

Julia Passynkova
Julia Passynkova

Reputation: 17859

You can use publishLast with refcount. publishLast is multicast operator with AsyncSubject that will execute the observable once and remember.

Something like that:

rows$ = Observable.of([1, 2, 3]).do(x => 
                   console.log(x)).publishLast().refCount();

Upvotes: 1

Related Questions