I have a component HospitalComponent
that tries to show a list of hospitals. It uses the readAll
method from the HospitalService
(that returns an Observable from firebase) :
ngOnInit() {
this.hospitalService
.readAll() // Make a firebase call
.subscribe(hospitals => this.hospitals = hospitals);
}
The route /hospital
is plugged to this component HospitalComponent
. Each time I reach /hospital
, Angular 2 make a new HospitalComponent
, and a new call is made to the hospitalService
.
Each time I reach /hospital
, the hospital list is showing with delay.
Is it a good practice to retrieve the hospital list from the service constructor itself ? This way, I can manage the refresh list from background, instead of having some delay. I would have in the component :
ngOnInit() {
this.hospitals = this.hospitalService.readAll();
}
and in the service :
constructor(private hospitalService: HospitalService) {
hospitalService.subscribe(hospitals => this.hospitals = hospitals);
}
But this implies to manage manually all hospital changes ..
From a technical viewpoint both "solutions" are pretty much equal - since they basically do the same thing it is up to your personal taste if you just want to conside your two solutions.
But in general: Try to avoid manual subscriptions at all.
There are a couple things that you can improve (the following code is based on the assumption, that you'd rather show an outdated list, that is updated in the background than to show a loading-indicator):
async
-pipe instead Your Service
export class HospitalService {
allHospitals$: BehaviorSubject<IHospital[]> = new BehaviorSubject<IHospital[]>([]);
// the fetchAll() method can be called in the constructor, or somewhere else in the application e.g. during startup, this depends on your application-flow, maybe some login is required ect...
fetchAll(): Observable<IHospital[]> {
const fetch$: Observable<IHospital[]> = ...get_stuff_from_firebase().share();
fetch$
.do(allHospitals => this.allHospitals$.next(allHospitals);
.subscribe();
return fetch$; // optional, just in case you'd want to do something with the immediate result(or error) outside the service
}
}
Your component (=> just inject the service)
constructor(private hospitalService: HospitalService) {
// nothing to do here
}
The template of the component (=> the async-pipe automatically manages the subscription and unsubscribes automatically as well, so you don't have to worry about memory-leaks ect...)
<div *ngFor="let hospital of (hospitalService.allHospitals$ | async)">
{{hospital.name}}
</div>
A fourth(but much more extended) solutions would be to use a central store like ngrx - So with ngrx basically the part of allHospitals$
would be moved to a centrally managed store-module and you would strictly divide up your application, so that a service will do nothing but fetching and processing data, the store will do nothing but storing and emitting data and a component will do nothing but displaying data.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.