Now, the above function returns new http observable each function call??
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
Approach:1
To Avoid Duplication of HTTP Requests you can use shareReplay
operator.
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);
});
}
Further Reading
Live Demo
Approach:2
If your objective is to multicast the data use RXJS's Subject
or BehaviorSubject
Subject
acts as a bridge/proxy between the source Observable
and many observers
, making it possible for multiple observers
to share the same Observable
execution.
This recommended way of exposing Subjects are using the asObservable()
operator.
@Injectable()
export class MyProvider {
private myObservable=new Subject<any>();
CurrentData = this.myObservable.asObservable();
constructor(private aFs: AngularFirestore) {
//your logic
this.myObservable.next(value);//push data into observable
}
}
Page.ts
this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
//something that works
});
Using Behavior Subject
@Injectable()
export class MyProvider {
private myObservable = new BehaviorSubject<any>("");
CurrentData = this.myObservable.asObservable();
constructor(private aFs: AngularFirestore) {}
getData(myParam): void {
someasynccall
.pipe(
map(),
filter()
)
.subscribe(value => this.myObservable.next(value));
}
}
Page.ts
this.myProvider.getData(param);
this.mySubscription = this.myProvider.CurrentData.subscribe(value => {
//something that works
});
Subject vs BehaviorSubject
LiveDemo
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…