【问题标题】:using BehaviorSubject in a service?在服务中使用 BehaviorSubject?
【发布时间】:2018-03-13 13:03:52
【问题描述】:

我的服务代码如下:

private caseListSource = new BehaviorSubject({});
caseList$ = this.caseListSource.asObservable();

loadCaseList() {
    return this._httpClient.get<Case>(environment.api_url +'/cases').do(data =>{
      this.caseListSource.next(data);

    });

在我的组件中,我正在执行以下操作:

caseList:any;

ngOnInit() {
   this.subscription = this._caseService.loadCaseList().subscribe(data => 
                                                                this.caseList = data);
  }

目前,我正在使用 doBehaviorSubject 上调用 next。有一个更好的方法吗?我应该在 m subscribe 调用中调用 .next() 吗?我会在每个想要通知的组件中调用next 吗?

最初我没有使用BehaviorSubject,但是当我登录到我的应用程序并转到select 路由时,选择组件中的ngOnInit 将填充caseList,我将在另一个中使用它组件也是如此。一旦我刷新了诸如case\2988 之类的页面,caseList 就会以未定义的形式返回。

【问题讨论】:

  • 所以你使用BehaviorSubject作为缓存?
  • @martin - 我可能更新了我最初的问题的帖子。
  • 也许您可以将流 (this._httpClient.get...) 保存为公共属性(或通过函数公开)并将 shareReplay(1) 运算符放在末尾。然后当有人第一次订阅时,它会调用它并与所有未来的订阅者分享结果。
  • 我对使用 BehiavorSubject 而不是在服务中使用共享变量感到有些困惑。如果我使用共享变量创建服务甚至覆盖它们,角度组件也会检测到这些变化,那我为什么要使用 BehiavorSubject 而不是共享变量呢?例如,一个数组。

标签: angular rxjs behaviorsubject


【解决方案1】:

为什么要创建 3 个不同的 Observable?

private caseListSource = new BehaviorSubject({}); 是一个 Observable;

caseList$ = this.caseListSource.asObservable(); 是一个 Observable;

return this._httpClient.get&lt;Case&gt;(environment.api_url +'/cases') 是另一个 Observable;

只需在loadCaseList 中返回http 调用,您就会得到可观察到的http 调用响应。类似:

loadCaseList() {

  return this._httpClient.get<Case>(environment.api_url +'/cases');

}

如果您想维护 Observable 的副本,可以将调用分配给私有变量,例如:

loadCaseList() {

  this.caseListSource = this._httpClient.get<Case>(environment.api_url +'/cases');

  return this.caseListSource;

}

更新

您似乎正在使用 BehaviorSubject 为 Observable 提供初始值。

如果为真,您可以使用SwitchMap 在组件初始化时实例化的BehaviorSubject 和HTTP 调用的返回之间切换:

private caseListSource = new BehaviorSubject({}); // creates the behaviorSubject with an initial value

loadCaseList() {

  return this.caseListSource.switchMap(() => {

    return this._httpClient.get<Case>(environment.api_url +'/cases');

  });

}

这样你就可以获得初始值,然后在loadCaseList被调用后切换到http调用。

【讨论】:

  • 我确实是这样做的,因为我看到的每个使用 BehaviorSubject 的示例都是这样做的。我更新了我的帖子为什么我开始使用一个?
  • 我已更新我的答案以显示 switchMap 的用法。
  • caseListSource 值在您的示例中未更新,这违背了将其用作缓存的目的。
【解决方案2】:

如果您只想在应用程序启动时发出一个请求,那么BehaviorSubjects 很有用。

如果是这样,那么你的组件应该订阅主题:

ngOnInit() {
   this.subscription = this._caseService.caseList$
     .subscribe(data => this.caseList = data);
}

如果您不关心发出多个请求,那么您不应该使用它。

(这是我的观点和做事方式,我可能是错的,所以不要相信我的话是绝对唯一的真理)

【讨论】:

  • 我认为 BehaviorSubject 的重点是所有订阅它的组件都会在每次发出请求时得到通知?
  • 主题也是如此,但我是在向你解释当你做你想做的事情时,行为主题是如何被用作缓存的。
猜你喜欢
  • 2017-11-18
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 2022-12-17
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 2018-01-24
相关资源
最近更新 更多