繁体   English   中英

组件被销毁并重新访问后,订阅在 ngOnInit function 中运行

[英]Subscription runs in ngOnInit function after Component is destroyed and Revisited

对于 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();
}

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

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订阅,即使在离开时组件被破坏后也是如此。 如何防止这种情况发生? 我也尝试过定义订阅变量并调用unsubscribe 我难住了。

为了扩展我的评论,RxJS BehaviorSubject保存推送给它的当前值并在订阅时立即发出它。 它还允许您在BehaviorSubject上使用唯一的getValue() function(或value getter),从而允许您同步检索它持有的当前值。 虽然这个 getter 的使用通常是不受欢迎的。

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

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

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

因此, ReplaySubject(1) (缓冲区 1)类似于BehaviorSubject ,只是它不需要默认值。 因此,如果您在尚未向其中推送任何内容时订阅它,则它不会发出。

它对当前问题没有帮助,但在您希望拥有 BehaviorSubject 的BehaviorSubject但不希望处理不必要的默认值的情况下可能会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM