我有一个组件HospitalComponent
,试图显示医院列表。它使用readAll
中的HospitalService
方法(从firebase返回一个Observable):
ngOnInit() {
this.hospitalService
.readAll() // Make a firebase call
.subscribe(hospitals => this.hospitals = hospitals);
}
路由/hospital
已插入此组件HospitalComponent
。每当我到达/hospital
时,Angular 2都会生成一个新的HospitalComponent
,并且会对hospitalService
进行新的调用。
每次到达/hospital
时,医院列表都会延迟显示。
从服务构造函数本身检索医院列表是一个好习惯吗?这样,我可以从后台管理刷新列表,而不是有一些延迟。我会在组件中:
ngOnInit() {
this.hospitals = this.hospitalService.readAll();
}
并在服务中:
constructor(private hospitalService: HospitalService) {
hospitalService.subscribe(hospitals => this.hospitals = hospitals);
}
但这意味着要手动管理所有医院的变化。
答案 0 :(得分:8)
从技术角度来看,"解决方案"几乎是相同的 - 因为他们基本上做同样的事情,如果你只想考虑你的两个解决方案,这取决于你的个人品味。
但总的来说:尝试完全避免手动订阅。
有几件事你可以改进(以下代码基于这样的假设,你宁愿显示一个过时的列表,在后台更新,而不是显示加载指示器):< / p>
async
- 管道代替您的服务
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
}
}
您的组件(=&gt;只是注入服务)
constructor(private hospitalService: HospitalService) {
// nothing to do here
}
组件的模板(=&gt; async-pipe自动管理订阅并自动取消订阅,因此您不必担心内存泄漏等...)
<div *ngFor="let hospital of (hospitalService.allHospitals$ | async)">
{{hospital.name}}
</div>
第四个(但更加扩展的)解决方案是使用像ngrx这样的中央商店 - 所以对于ngrx,基本上allHospitals$
的部分将被移动到集中管理的商店模块而你会严格划分您的应用程序,以便服务除了提取和处理数据之外什么也不做,商店除了存储和发送数据之外什么也不会做而组件会做< em>只显示数据。