【问题标题】:How to prevent calling same api in different components如何防止在不同组件中调用相同的api
【发布时间】:2020-04-16 14:45:48
【问题描述】:

我有一个医生服务,它有如下 API 调用

patientDetails():Observable<any>
 {
   return http.get("/home/patient-details")
 }

上述服务我订阅了不同的模块组件以获取患者详细信息。在这里我在想如何防止在多个组件中重复 API 调用?

是否可以选择只调用一次 API 并在项目之间共享数据

【问题讨论】:

标签: angular


【解决方案1】:

HttpClient 的方法返回 Cold Observable。要实现您想要的功能,您需要 Hot Observable。您可以使用 shareReplay(numberOfEventsToShare) 将 Cold Observable 转换为 Hot Observable(也称为 Warm Observable,因为它会变暖)并将其存储在属性中。要了解为什么需要这个运算符,您需要知道 Observable 是 Hot 或 Cold 的含义。看看这个great article。

但简而言之,对于您的情况:Hot Observable 共享一个生产者,该生产者甚至可以在有人订阅他之前就产生价值。另一方面,Cold Observable 为每个观察者创建生产者(这意味着不同的观察者之间不会共享该状态)。

因此,shareReplay(1) 运算符将通过共享源并为所有观察者重播 1 个事件(也适用于未来的观察者),使 HttpClient 温暖返回的 observable。

我创建了一个StackBlitz demo,你可以看到即使添加了新组件也没有后续的HTTP请求。

【讨论】:

    【解决方案2】:
    public patientDetails$: Observable<any>;
    
    constructor(...) {
        this.patientDetails$ = http.get("/home/patient-details").pipe(shareReplay(1));
    }
    

    【讨论】:

    • 你能详细说明一下你的答案吗
    • 您可以在您的服务中创建一个属性,然后将其设置为 http observable。 shareReplay(1) 将在订阅者订阅时分享最后的结果
    • 虽然这可能会回答作者的问题,但它缺少一些解释性文字和/或文档链接。如果没有围绕它们的一些短语,原始代码 sn-ps 并不是很有帮助。您可能还会发现how to write a good answer 非常有帮助。请edit你的答案-From Review
    【解决方案3】:

    我相信Bardr 和that_guy 提供的答案都需要在服务启动时调用API(因为它们是在构造函数中调用的)。

    我希望对多个组件进行非重复的 API 调用,但前提是任何组件都需要该调用。所以它不能依赖于构造函数。我决定以下列方式实现它,其中检查支持的 observable 的值,并且只有当支持的 observable 的值为 null 时才会调用 API。或许可以将此模式与上述答案结合起来。

    为我服务:

    private foobarReference = new BehaviorSubject<FoobarReference>(null);
    public foobarReference$ = this.foobarReference.asObservable();
    public getFoobarReferences(): Observable<FoobarReference> {
        if (this.foobarReference.getValue() == null) {
            this.httpClient.get<FoobarReference>('/api/references/foobar/').subscribe(data => this.foobarReference.next(data));
        }
        return this.foobarReference$;
    }
    

    在我的组件中,我像其他任何 observable 一样订阅它(我使用 takewhile,因为 observable 在服务生命周期内不会改变值):

    private this.foobarReferences: FoobarReference;
    this.foobarService.getFoobarReferences().pipe(takeWhile(x => x == null, true)).subscribe(data => this.foobarReferences = data);
    

    【讨论】:

      猜你喜欢
      • 2020-03-16
      • 1970-01-01
      • 2021-12-31
      • 2018-05-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 2017-09-11
      • 1970-01-01
      相关资源
      最近更新 更多