在路由器订阅中调用订阅方法时,我是否应该取消从ActivatedRoute订阅?

时间:2020-07-06 18:29:05

标签: angular angular-activatedroute rxjs-subscriptions

我了解到,通常您不必明确地退出RouterActivatedRoute的订阅,因为:

ActivatedRoute及其可观察物与路由器绝缘 本身。当路由组件不再存在时,它会销毁它 需要,注入的ActivatedRoute随之死亡。

来源:Do I have to unsubscribe from ActivatedRoute (e.g. params) observables?

但是,我在父组件subscribe()中反复在ActivatedRoute.firstChild.paramMap上调用app.component。仅当用户离开Web应用程序或关闭网站时,此组件才会被销毁,因此我担心那些paramMap订阅可能会一直保持活动状态。

订阅调用在Router.events订阅中进行,如下所示:

this.routerSubscription = this.router.events
  .pipe(
    tap((event) => { 
      switch (true) {
        case event instanceof NavigationStart: { 
          setTimeout(() => this.showChildComponentLoading = true);
          break;
        }

        case event instanceof NavigationEnd:{
          this.activatedRoute.firstChild.paramMap.subscribe(paramMap => {
          if(paramMap.has('mode')){
              let newWebAppMode:string = paramMap.get('mode');
              if(this.dataStoreService.isValidWebAppMode(newWebAppMode) && newWebAppMode !== this.dataStoreService.currentAppMode)
                  this.saveToLocalStorage.next([DataType.WEB_APP_MODE, newWebAppMode]); 
          }
        });
//other code

每次有人导航到另一个组件/页面activatedRoute.firstChild.paramMap时,都会再次订阅。我仅在事件为NavigationEnd的实例时才在路由器订阅中执行此操作,因为在此之前url参数尚不可用。

我的问题是,这些订阅会如何处理?他们是自动退订还是我需要手动退订每个新的?如果是后者,我该如何有效地做到这一点?

有些人可能建议我使用activatedRoute.firstChild.snapshot.paramMap.myParameter,因为那样我就不必订阅任何东西。但是,在重用相同组件的同时url参数更改时,snapshot不起作用。所以我不能使用它。

谢谢

2 个答案:

答案 0 :(得分:1)

是的,它看起来确实像是潜在的内存泄漏:每个NavigationEnd上都会产生一个新订阅,因此您可能无限制地拥有相同流的相同观察者(并且activatedRoute.firstChild.paramMap会无限期地发出)。您可以通过在订阅中放入简单的console.log(new Date())来进行验证。

我相信switchMap是您的朋友(订阅新流后,它会自动从旧流中退订)。像

this.router.events.pipe(
    filter(event => event instanceof NavigationEnd),
    switchMap(() => this.activatedRoute.firstChild.paramMap),
    filter(paramMap => paramMap.has('mode')),
    map(paramMap => paramMap.get('mode')),
    filter(newMode => this.dataStoreService.isValidWebAppMode(newMode) && 
        newMode !== this.dataStoreService.currentAppMode),
).subscribe(newMode => this.saveToLocalStorage.next([DataType.WEB_APP_MODE, newMode]);

顺便说一句,您是否需要防止this.activatedRoute.firstChild为空?

答案 1 :(得分:0)

在这些情况下无需退订

  1. 在HttpClient调用的情况下,因为可观察对象发出一个值(成功或错误)并自动完成。

  2. 以防万一或ActivatedRoute预订,因为当组件自动销毁时,路由器会销毁它

  3. 使用异步管道