Angular 2 从组件或服务订阅?

标签 angular firebase rxjs observable angularfire2

上下文

我有一个组件 HospitalComponent 试图显示医院列表。它使用 HospitalService 中的 readAll 方法(从 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);
}

但这意味着要手动管理所有医院变更..

最佳答案

从技术 Angular 来看,这两种“解决方案”几乎相同 - 因为它们基本上做同样的事情,所以如果您只想考虑您的两种解决方案,则取决于您的个人喜好。

但总的来说:尽量避免手动订阅

有几件事您可以改进(以下代码基于假设,您宁愿显示一个过时的列表,在后台更新而不是显示加载指示器):

  • 尽量避免手动订阅(尤其是(!!)在组件中)-> 使用 async-pipe 代替
  • 尽量避免有状态的组件(如果可能,甚至是服务)-> 使用流来代替

您的服务

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
    }
}

您的组件(=> 只需注入(inject)服务)

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

组件的模板(=> async-pipe 自动管理订阅和自动取消订阅,所以你不必担心内存泄漏等......)

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

第四种(但更广泛)解决方案是使用中央存储,如 ngrx - 因此,对于 ngrx,allHospitals$ 的部分基本上将被移动到一个集中管理的存储模块中,您将严格划分您的应用程序,这样一个服务将除了获取和处理之外什么都不做 数据,商店将除了存储和发送数据外什么都不做,而组件将除了显示数据外什么都不做。

关于Angular 2 从组件或服务订阅?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41021487/

相关文章:

javascript - 使用 null 值填充 FormGroup 并

firebase - 如何在flutter中将 ListView 制作为listview.builder?

firebase - 通过flutter在Firestore中添加嵌套数据

angular 2 material keyup.enter 根本不触发

angular - 更改 Angular Material 表中的行颜色

angular - 在 Angular 5 中单击关闭 Angular2 通知时出现 ViewDestroyedError

firebase - Firebase 应用的并发用户数到底是如何确定的?

node.js - nestjs 中的 Rxjs - 可观察到的订阅错误

rxjs - 递归可观察

javascript - Angular try catch 与捕获错误