【问题标题】:Angular observable not updating automaticallyAngular observable 不会自动更新
【发布时间】:2020-09-09 19:08:28
【问题描述】:

我有一个服务,我向其传递了一个值,因此该值可供所有需要它的组件使用:

  setAnalysisStatus(statuses: AsyncAnalysis[]) {
    this.analysisStatus.next(statuses);
  }

我有一个使用按钮单击显示的组件。显示的组件调用另一个方法订阅analysisStatus

  getAnalysisStatus(): Observable<AsyncAnalysis[]> {
    return this.analysisStatus.asObservable();
  }

组件订阅如下:

ngOnInit(){
this.changeGroupService.getAnalysisStatus()
.subscribe(result => {
  result.forEach(item => {
    this.changeGroupStatus.forEach((changeGroup, index) => {
      if (item.changeGroupId === changeGroup.id) {
        this.changeGroupStatus[index].name = this.changeGroupStatus[index].name;
        this.changeGroupStatus[index].status = item.status;
      }
    });
  });
});
}

当我触发该组件时,它会显示analysisStatus 的当前状态。但是,当它的状态发生变化时,组件不会更新。如果我关闭然后重新打开该组件,它会显示新状态。我需要它来显示状态并在analysisStatus 的状态发生变化时更新。

analysisStatus 是这样设置的:

analysisStatus = new BehaviorSubject&lt;AsyncAnalysis[]&gt;([]);

我的假设是通过this.changeGroupService.getAnalysisStatus() 订阅应该寻找更新this.changeGroupStatus 中的值。我错过了什么吗?

编辑---

所以在我的ngOnInit 中检查this.changeGroupService.getAnalysisStatus() 我可以看到result 的值实际上会根据需要进行更新,但模板不会更新以反映更改。

【问题讨论】:

    标签: angular observable behaviorsubject


    【解决方案1】:

    看起来模板中呈现的值并不直接依赖于 observable 中的值。此外,变量changeGroupStatus 未分配新值。它只有很少的属性被改变。 Angular 可能无法检测到部分更改。在这些情况下,您可以尝试使用ChangeDetectorRef 手动触发更改检测。试试下面的

    import { pipe, Subject } from 'rxjs';
    import { takeUntil } from 'rxjs/operators';
    
    destroyed = new Subject<void>();
    
    ngOnInit(){
      this.changeGroupService.getAnalysisStatus().pipe(
        takeUntil(this.destroyed)
      ).subscribe(result => {
          result.forEach(item => {
            this.changeGroupStatus.forEach((changeGroup, index) => {
              if (item.changeGroupId === changeGroup.id) {
                this.changeGroupStatus[index].name = this.changeGroupStatus[index].name;
                this.changeGroupStatus[index].status = item.status;
              }
            });
          });
          this.cdr.detectChanges();           // <-- trigger change detection here
        });
    }
    
    ngOnDestroy(): void {
      this.destroyed.next();
      this.destroyed.complete();
    }
    

    更新

    您可以在 takeUntil 运算符中使用 observable(这将在 ngOnDestroy 挂钩中完成)来避免内存泄漏问题。但是当多个组件中有多个订阅时,它可能会变得乏味。我在这里看到的这个问题有一个更好的解决方案:https://stackoverflow.com/a/45709120/6513921

    【讨论】:

    • 请问,在嵌套循环中调用detectChanges 肯定会影响性能,并可能产生意想不到的效果。考虑移到循环之外调用一次。另一件事我还没有测试过,但我相信如果您使用 mapreduce 重新创建数组,而不是使用 forEach 对其进行变异,您甚至不需要使用 ChangeDetectorRef
    • @developer033:这是一个有效的观点。我已经修改了代码。我也不确定使用map/reduce 是否会触发默认更改检测。但这是个好主意。
    • 离开组件后一定要销毁订阅,否则会出现内存泄漏。
    猜你喜欢
    • 2016-08-20
    • 1970-01-01
    • 2019-01-20
    • 2018-01-24
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多