angular - 在第一个值发射后,主体从数组中失去观察者。 Angular RouteReuseStrategy 表编辑表单通信

标签 angular rxjs angular-router subject-observer

我的用例是列表 - 详细信息 View (主从 View ,试图摆脱掌握术语)。

我通过路由到编辑表单并通过使用主题的数据服务在路由/组件之间传递保存的值来编辑表中的记录。

记录的第一次编辑有效,第二次则无效,并且我的主题失去了对列表组件中监听表单/详细信息条目最新更新的观察者的引用。我正在使用 Angular 路由来缓存组件实例,当重新附加路由时,我注意到存储的可观察对象仍然引用了主题。然而,在收到第一个值后,观察者在源主题上丢失,并且观察者随后重新附加任何路由/组件,都不会使用通过服务订阅来引用主题<->可观察到的对象。我正在使用该服务充当两条路线之间的推送/桥梁。我现在的解决方案是让组件通过 AfterViewChecked 生命周期进行订阅,但这似乎很昂贵,我想找到更多设置并忘记的东西。当发出第一个值时,数据服务使用Subject asObservable() 方法。在发出时,asObservable 的监听器/调用者接收新值。在第二次发射/下一个值时,主体失去了观察者,因此我的订阅者/组件无法接收该值。

**我的数据服务方式: **

    private taskDetailViewSubject: Subject<Task> = new Subject<Task>();

    getTaskUpdated(): Observable<Task> {
      return this.taskDetailViewSubject.asObservable();
    }
    pushTaskUpdate(task: Task): void {
      this.taskDetailViewSubject.next(task);
    }

**我的列表/表格组件根据调用 getTaskUpdated() 的表单编辑订阅更新行: **

    this.getUpdatedRows = this.taskTableService.getTaskUpdated().pipe(
      map((task: Task) => this.taskTableService.getTaskRow(task)),
      filter((task: TaskRow) => !!task),
      tap((newRow) => this.updateRow(newRow, null))
    );
    this.getUpdatedRows.subscribe();

**我的详细信息条目/表单组件推送方法,在保存时我们通过pushUpdateMethod($event)传递新值: **

    pushUpdate($event: Task) {
      this.taskTableService.pushTaskUpdate($event);
    }

**我的侦查屏幕截图 ** 第一次编辑并重新附加路线: Table component push update subscription Data service pushing update to observer in table

在主体失去观察者引用的情况下进行第二次编辑和重新连接路线: 使用控制台日志检查订阅,因为没有发出任何值 Table component push update subscription - using console log to inspect the subscription Data service pushing update to observer in table of second value

非常感谢任何见解,这个问题让我非常困扰。

在将订阅放入 AfterViewChecked 生命周期之前我尝试过一些东西,它有效,但它是一个黑客...... 我尝试不使用 asObservable() 并返回主题。我删除了组件中观察者上的 takeUntil 。我在放置修复的地方放置了一个控制台日志,这样我就可以检查观察者的订阅。 我尝试了一个行为主体,但令人惊讶的是没有观察者附加,并且监听组件没有收到任何值(value)。 与主题不同,第一次编辑未能传递令人惊讶的值。 Table initialization and subscription does not add observer to behavior subject

编辑-----

我发现,如果我以声明性方式内联而不是通过生命周期初始化属性,则订阅不会丢失。我将进行 stackblitz 来展示这一点并找出我所看到的问题中的漏洞。

最佳答案

我认为您可以尝试使用 BehaviorSubject 而不是 Subject,以便缓存最后发出的值,并且在(重新)订阅时,订阅者将始终收到最新值。

因此您的服务可能如下所示:

private taskDetailViewSubject: BehaviorSubject<Task> = new BehaviorSubject<Task>(null);

public taskDetailView$: Observable<Task> = this.taskDetailViewSubject.asObservable();

pushTaskUpdate(task: Task): void {
  this.taskDetailViewSubject.next(task);
}

对于您的组件,我真的建议添加一种机制,当组件被销毁时,该机制可以取消订阅源可观察的内容(否则您将面临恼人的副作用,例如您的管道被多次执行连续多次):

private unsubscribe = new Subject<void>(); // Will notify the pipes about unsubscribing

ngOnInit(): void {
  // I think here you could directly subscribe to the pipe?:
  this.taskTableService.taskDetailView$.pipe(
    map((task: Task) => this.taskTableService.getTaskRow(task)),
    filter((task: TaskRow) => !!task),
    tap((newRow) => this.updateRow(newRow, null)),
    takeUntil(this.unsubscribe) // unsubscribes when this.unsubscribe.next() is called onDestroy
  )
  .subscribe();
}

ngOnDestroy(): void {
    this.unsubscribe.next(); // unsubscribe when component gets destroyed
}

关于angular - 在第一个值发射后,主体从数组中失去观察者。 Angular RouteReuseStrategy 表编辑表单通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75023743/

相关文章:

javascript - RXJS6 - 从返回 Observable 的 Promise 函数返回 Observable?

angular - 在 canActivate Guard 中访问 ActivatedRoute 的组件

html - 如何在 Angular 中为 ng-otp-input 包的输入字段赋予边框颜色?

javascript - 在组件 Angular 2 中重定向

javascript - 由于 Observable 订阅发生在组件上,因此我很难将逻辑重构到 Angular 2 应用程序的服务层中

javascript - rxjs 在订阅时只使用一次 promise

angular - 如何在 Angular 2 的 HTML 文件中使用 routerLink?

带参数的 Angular 路由重定向到

angular - 如何以编程方式从组件类中选择 Angular 引导导航选项卡

angular - 如何在 Angular 中显示分组数组?