我的用例是列表 - 详细信息 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)。 与主题不同,第一次编辑未能传递令人惊讶的值。
编辑-----
我发现,如果我以声明性方式内联而不是通过生命周期初始化属性,则订阅不会丢失。我将进行 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/