繁体   English   中英

组件销毁后,可观察订阅保持活动状态

[英]Observable subscription remains active after component has been destroyed

我的一个组件订阅路由器事件,如下所示:

    this.navigationSubscription = this.router.events.subscribe((e: any) => {
      // If it is a NavigationEnd event re-initalise the component
      if (e instanceof NavigationEnd) {
        let p = e as NavigationEnd;
          console.log(p.urlAfterRedirects);
        console.log("im being called from NavigationEnd");
        this.ngOnInit();
      }
    });
   }

当用户通过按钮第二次导航到组件时,我使用此代码重新加载组件。 在调试问题时,我注意到当我导航到另一个组件时,这段代码仍然保持活动状态,即使它所在的组件不是。 有人可以解释为什么以及如何即使组件本身不再存在此代码仍保持活动状态? 当代码无法再到达this.ngOnInit()时,它不应该导致错误吗?

我可以通过在 onDestroy 方法中取消订阅来解决这个问题,但我真的很想知道当组件不再存在时代码如何能够保持活动状态,以及为什么this.ngOnInit()不会抛出错误,因为组件未激活。

一个物理世界的例子,以及我如何理解订阅:如果我订阅了一份报纸到我的街道地址,我的房子被毁了(插入糟糕的场景),我仍然必须取消订阅,否则报纸会堆积在烧毁了曾经是我家的一堆东西。

一般而言,所有订阅在组件销毁后都保持活动状态。

这是 Angular IMO 的一大难题。

但是,此规则有一些例外:

  • this.activatedRoute.params.subscribe - 自动取消订阅
  • this.activatedRoute.data.subscribe - 自动取消订阅
  • 任何 http 订阅 - 这些将发出一次然后完成,因此无需取消订阅
  • 异步管道自动取消订阅

对于其他所有内容,您需要手动取消订阅。 有多种方法可以做到这一点,但这里是 RxJs 推荐的方法:

private unsubscribe$ = new Subject()

this.someobservable.pipe(
  takeUntil(this.unsubscribe$)
).subscribe( .... )

ngOnDestroy() {
  this.unsubscribe$.next()
  this.unsubscribe$.complete()
}

有人可以解释为什么以及如何即使组件本身不再存在此代码仍保持活动状态?

虽然该组件“不再存在”,但这仅意味着指向其中存储的Subscription实例的指针消失了,但订阅仍然是“活动的”,并且很可能被router.events流跟踪,这解释了为什么 GC不能简单地从内存中删除实例。

当代码无法再到达 this.ngOnInit() 时,它不应该导致错误吗?

很可能与第一点有关,因为 GC 无法释放组件实例。

暂无
暂无

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

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