Reputation: 17773
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?
Thanks for answers, but they just don't focus on the real issue. Let's me rephrase it.
Suppose I have a observable variable myObservable
returned by Http
service
Suppose in template I'm using this variable with async
pipe
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
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
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
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