提问者:小点点

组件被销毁和重访后,订阅在ngOnInit函数中运行


我遇到了Angular组件和rxjs订阅的非常奇怪的情况。

我有以下ngOnInitngOnDestroy函数

ngOnInit() {
    zip(this.service.getMessage, this.service.getType)
      .pipe(takeUntil(this.componentDestroyed$))
      .subscribe(data => {
        const notification = new Notification(data[0], data[1]);
        this.notifications.push(notification);
    });
}

ngOnDestroy(): void {
    this.componentDestroyed$.next(true);
    this.componentDestroyed$.complete();
}

在如下所示的服务文件中使用源和主题范例设置值后,订阅处于活动状态:

private messageSource = new BehaviorSubject<string>('');
private message = this.messageSource.asObservable();
private typeSource = new BehaviorSubject<number>(-1);
private type = this.typeSource.asObservable();

...
...

set setMessage(message: string) {
  this.messageSource.next(message);
}

set setType(type: number) {
  this.typeSource.next(type);
}

初始订阅工作正常,正如预期的那样。但是,从组件导航并导航回同一个组件会在ngOnInit中再次运行zip订阅,即使在导航离开时组件被销毁之后也是如此。如何防止这种情况发生?我还尝试过定义订阅变量并调用un订阅。我被难倒了。


共1个答案

匿名用户

为了扩展我的评论,RxJSBe行为主体保存推送到它的当前值,并在订阅时立即发出它。它还允许您在Be行为主体上使用唯一的getValue()函数(或valuegetter),允许您同步检索它持有的当前值。尽管使用这个getter通常是不赞成的。

因此,在您的情况下,当您路由回组件时,订阅会通过两个可观察对象发出先前持有的值。相反,您可以使用不保存值并仅在将值推送到它之后才发出的RxJS主题

private messageSource = new Subject<string>();
private message = this.messageSource.asObservable();
private typeSource = new Subject<number>();
private type = this.typeSource.asObservable();
...

我还建议您查看RxJSReplaySub。它是一种更灵活的多播可观察对象。它接收要缓冲的通知数量,并在新订阅时立即发出它们。

因此,ReplaySub(1)(buffer 1)类似于行为主题,只是它不需要默认值。因此,如果您在没有任何内容插入时订阅它,它将不会发出。

它不能帮助您解决当前问题,但在您希望具有行为主体的行为但不希望处理不必要的默认值的情况下可能会有所帮助。