0

我读到通常您不必取消订阅RouterActivatedRoute明确地取消订阅,因为:

ActivatedRoute 及其 observables 与 Router 本身是绝缘的。当不再需要路由组件并且注入的 ActivatedRoute 随之消亡时,Router 会销毁路由组件。

来源:我是否必须取消订阅 ActivatedRoute(例如 params)observables?

但是我在父组件subscribe()中反复调用。只有当用户离开 Web 应用程序或关闭网站时,该组件才会被销毁,所以我担心这些订阅可能会一直保持活动状态。ActivatedRoute.firstChild.paramMapapp.componentparamMap

订阅调用是在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,因为这样我就不必订阅任何东西了。但是,snapshot当 url 参数更改而同一组件被重用时,它不起作用。所以我不能用那个。

谢谢

4

2 回答 2

2

是的,它看起来确实像一个潜在的内存泄漏:每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为空吗?

于 2020-07-06T21:30:36.370 回答
0

在这些情况下无需取消订阅

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

  2. 万一或ActivatedRoute订阅,因为Router会在组件自动销毁时销毁它

  3. 使用异步管道

于 2020-07-06T18:41:30.547 回答