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 ..
Normally Subscription means an arrangement to receive something. Similarly, in Angular applications Observables will be connected to observers and whenever they observe a new value or change in data, they will execute code with the help of Subscription and all the subscribed components will receive the updated outcome.
In ServicesThere is no reason for the service itself to subscribe. Of course, a service might call another service, and get back an Observable. You (as the author of the first service) might consider subscribing to the Observable, but remember: your service only made that call because it was itself called.
As you probably know when you subscribe to an observable or event in JavaScript, you usually need to unsubscribe at a certain point to release memory in the system. Otherwise, you will have a memory leak.
subscribe() is a method on the Observable type. The Observable type is a utility that asynchronously or synchronously streams data to a variety of components or services that have subscribed to the observable.
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 insteadYour 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With