代码之家  ›  专栏  ›  技术社区  ›  Maurice

组件被销毁后,可观察订阅仍处于活动状态

  •  0
  • Maurice  · 技术社区  · 7 年前

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

        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方法中取消订阅来解决这个问题,但是我真的很想知道当组件不再存在时代码是如何保持活动的,以及为什么 这个。恩戈尼特() 不会抛出并出错,因为组件未处于活动状态。

    3 回复  |  直到 7 年前
        1
  •  3
  •   Bytech    7 年前

    一个物理世界的例子,以及我如何理解订阅:如果我订阅一份报纸到我的街道地址,而我的房子被摧毁(插入坏的场景),我仍然必须取消订阅,否则报纸将堆积在过去我的家的烧毁堆。

        2
  •  2
  •   danday74    7 年前

    一般来说,组件被销毁后,所有订阅都保持活动状态。

    这是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()
    }
    
        3
  •  1
  •   Jota.Toledo    7 年前

    有人能解释为什么和如何保持代码的活动性,即使 组件本身已经不存在了?

    尽管组件“不再存在”,但这只意味着指向 Subscription 存储在其中的实例已不存在,但订阅仍处于“活动”状态,很可能由 router.events stream,解释gc为什么不能简单地从内存中删除实例。

    当代码不能再到达时,它不应该引起错误吗? 这个.ngoninit()?

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

    推荐文章