Angular 2 subscribe to a component or service?

Context

I have a HospitalComponent component that is trying to show a list of hospitals. It uses the readAll method from HospitalService (which returns an Observable from firebase):

 ngOnInit() { this.hospitalService .readAll() // Make a firebase call .subscribe(hospitals => this.hospitals = hospitals); } 

The /hospital route is connected to this component of the HospitalComponent . Each time I reach /hospital , Angular 2 creates a new HospitalComponent , and a new call is made to the HospitalService .

Problem

Every time I reach /hospital , the list of hospitals shows with a delay.

Question

Is it good to retrieve the list of hospitals from the service designer? This way I can manage the update list from the background, and not have some delay. I would add to the component:

 ngOnInit() { this.hospitals = this.hospitalService.readAll(); } 

and in the service:

 constructor(private hospitalService: HospitalService) { hospitalService.subscribe(hospitals => this.hospitals = hospitals); } 

But this means that you need to manually manage all the changes in the hospital.

+5
source share
1 answer

From a technical point of view, both “solutions” are pretty much equal - since they basically do the same as your personal taste if you just want to consider your two solutions.

But in general: try to avoid manual subscriptions altogether.

There are a few things you can improve (the following code is based on the assumption that you would rather show an outdated list that is updating in the background than showing a download indicator):

  • try to avoid manual subscriptions (especially (!!) in components) -> use async -pipe instead
  • try to avoid stateful components (even if possible, if possible) → use threads 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 eg 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 enter the service)

 constructor(private hospitalService: HospitalService) { // nothing to do here } 

Component template (=> the asynchronous channel automatically automatically controls the subscription and automatically unsubscribes, so you don’t have to worry about ect memory leak ...)

 <div *ngFor="let hospital of (hospitalService.allHospitals$ | async)"> {{hospital.name}} </div> 

A fourth (but much more advanced) solution would be to use a central repository such as ngrx . Thus, ngrx is basically part of allHospitals$ will be moved to a centrally-managed storage module, and you will strictly separate your application so that the service does nothing but collect and process data, it will do nothing in the storage, except for storing and emitting data, and the component will do nothing but display the data.

+6
source

Source: https://habr.com/ru/post/1260934/


All Articles