【问题标题】:Angular: update a behaviorsubjectAngular:更新行为主体
【发布时间】:2021-06-23 18:04:36
【问题描述】:

我正在观看关于 RxJs 的 Angular 大学课程。一节描述了使用行为主体在商店服务中加载数据。

我尝试通过创建商店服务并在应用启动时对其进行初始化(我的 AppComponent)在我的 Angular 应用中实现它:

@Injectable({
  providedIn: 'root'
})

export class StoreService {

  constructor(private appService: AppService) { }

  private assetStatusSubject = new BehaviorSubject<IAssetStatusModel[]>([]);
  assetStatuses$: Observable<IAssetStatusModel[]> = this.assetStatusSubject.asObservable();

  init() {
    this.appService.getAssetStatuses().subscribe(
      (assetStatuses) => this.assetStatusSubject.next(assetStatuses)
    );

  }

  getAssetStatues() {
    return this.assetStatuses$;
  }

  refreshAssetStatuses () {
    this.appService.getAssetStatuses().subscribe(
      (assetStatuses) => {

        this.assetStatusSubject.next(assetStatuses);
        console.log('assetStatuses',this.assetStatuses$)
      }
    );

}

关键在于,这些很少更改的数据在应用程序的几个地方使用。以这种方式设置将避免每次加载某些组件时都必须进行多次 API 调用。

在 AppComponent 上,我调用 store service init() 函数来初始填充 observable:

this.storeService.init();

在我使用assetStatuses$ observable(在下拉列表中)的组件(组件A)上,我使用以下方法获取数据:

this.assetStatuses$ = this.storeService.getAssetStatues();

并将其绑定到我的下拉列表。这一切都很完美。

当我从状态组件(组件B)添加新状态时,我从组件调用存储服务中的刷新功能:

this.storeService.refreshAssetStatuses();

这似乎更新了商店中可观察到的assetStatuses$,因为我可以将其控制出来并且新增加的价值就在那里。但是,当我离开组件 A(在下拉列表中使用 observable 的组件)并返回到它时,即使我在 ngOnInit 中调用存储服务,它也会保留旧值:this.storeService.getAssetStatues( );

我不知道为什么这会返回旧值。如果我在浏览器中重新尝试一下,它们就会出现

感谢任何帮助。

编辑:

我还注意到一件事。在我的商店服务中,我有两个函数,一个用于更新 observable,另一个用于获取 observable,返回不同的值。如果我先调用刷新函数,添加新资产状态后,控制台显示它更新了assetStatuses$ observable:

  refreshAssetStatuses(): void {
    this.appService.getAssetStatuses().subscribe(
      (assetStatuses) => {
        this.assetStatusesSubject.next(assetStatuses);
        console.log('assetStatuses',this.assetStatuses$) // this has the new value
      }
    );
  }

之后,当我调用获取 observable 的函数(在同一服务中)时,控制台不会显示新值:

getAssetStatuses() {
    console.log('getAssetStatuses',this.assetStatuses$); // the new value is missing
    return this.assetStatuses$;
  }

我不明白这是怎么发生的,因为它们都引用了商店服务中的同一个可观察对象,并且首先调用的刷新清楚地显示了 assetsStatuses$ 已更新。

我很困惑:(

编辑 2:

我还要提到的另一件事是这两个组件是延迟加载的。我认为 provideIn: 'root' (从 Angular 6 开始)应该创建服务的单例实例。我正在研究这个以确保我的实现对于这种情况是正确的

【问题讨论】:

  • 不要直接引用组件中的 observable,而是尝试订阅它。
  • 我也试过了:this.storeService.assetStatuses$.subscribe((data) => { console.log('data', data)});但数据变量仍然是旧数据。
  • 你确定组件 A 真的被销毁了吗?尝试在 ngOnDestroy 中添加一个 console.log/debugger 并检查它是否真的被销毁了。
  • Lars:我编辑了我的帖子以显示商店服务中更新 observable 的函数具有新值。但是当我调用返回 observable 的函数(在同一个 servcie 中)时,它没有新值。在帖子中查看我的编辑。
  • 确保您的 StoreService 仅在一个 providers 数组中提供,否则它将为每个组件创建一个新实例。

标签: angular rxjs behaviorsubject


【解决方案1】:

我要检查的第一件事是确保对存储服务的引用在 AppComponent、组件 A 和组件 B 中是公开的。

您还推送到 this.businessUnitsSubject,但 observable 是基于 this.assetStatusSubject 推送到 this.assetStatusSubject 可能是您想要做的。

【讨论】:

  • 我在所有组件中都使用了DI:constructor(private storeService: StoreService) { }
  • 抱歉,这是一个复制/粘贴错误。我有不止一个可观察的我正在尝试这样做。我会更新这个问题。
  • 是的,所以您可以使用依赖注入,但如果您将其标记为私有,它会为每个组件注入不同的实例。将它们公开使得每个组件都引用相同的存储服务实例。所以这应该是构造函数(公共 storeService:StoreService){}。这就是我最初回复的第一部分的意思
【解决方案2】:

我的一位同事发现了这个问题。尝试对此进行测试时,我打开了两个浏览器选项卡。一个选项卡是组件 A,另一个是组件 B。行为主题特定于一个选项卡,它们不会在其他选项卡或其他浏览器窗口中更新。我认为至少它们会在浏览器选项卡之间共享。值得了解的宝贵信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    • 2020-12-06
    • 2023-03-27
    • 1970-01-01
    • 2022-09-25
    • 1970-01-01
    相关资源
    最近更新 更多