0

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?

dragonfly
  • 17,407
  • 30
  • 110
  • 219
  • when ever you toggle between components the component is created again that is the default behaviour of an angular app , you can change this by using canReuse so that component is not destroyed or recreated again and again, you can check this placing the lifecycle hook ngOnDestroy on the comp – Rahul Singh Jun 27 '17 at 09:50
  • But I don't mind creating/destroying the component. I'm just curious why each time pipe is subscribing to observable, it it executed. – dragonfly Jun 27 '17 at 09:55
  • because i guess in your component constructor or ngOnInit you might be calling this method right so this will in turn invoke that pipe – Rahul Singh Jun 27 '17 at 09:57
  • `fetch` method is called only once, and I reuse `Observable>` – dragonfly Jun 27 '17 at 09:57
  • sorry mybad the component template is loaded everytime the component is recreated so the pipe is invoked – Rahul Singh Jun 27 '17 at 09:58
  • I think you will find this post useful: https://stackoverflow.com/questions/35141722/how-does-the-rxjs-5-share-operator-work. I think you just need to use the SHARE operator. – Radu Cojocari Jun 27 '17 at 11:15

3 Answers3

3

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().

  • 1
    https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html explains what you wrote. Thx! – dragonfly Jul 02 '17 at 14:03
1

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();
Julia Passynkova
  • 17,256
  • 6
  • 33
  • 32
-3

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/

Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73