1

I've read that normally you don't have to unsubscribe from Router or ActivatedRoute explicitly because:

The ActivatedRoute and its observables are insulated from the Router itself. The Router destroys a routed component when it is no longer needed and the injected ActivatedRoute dies with it.

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

However I am calling subscribe() on ActivatedRoute.firstChild.paramMap repeatedly in the parent component app.component. This component is only destroyed when the user navigates away from the web application or closes the website so i'm worried that those paramMap subscriptions might remain active the entire time.

The subscription calls are made within a Router.events subscription and it looks like this:

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

Every time someone navigates to another component/page activatedRoute.firstChild.paramMap is subscribed to again. I have to do this inside the router subscription and only when the event is an instance of NavigationEnd because before that the url parameters are not yet available.

My question is, what happens to those subscriptions? Do they unsubscribe automatically or do i need to unsubscribe each new one manually? If the latter is the case, how can i do that effectively?

Some of you may advice me to use activatedRoute.firstChild.snapshot.paramMap.myParameter because then i don't have to subscribe to anything. However, snapshot does not work when the url parameter changes while the same component is reused. So i can't use that.

Thank you

1
  • when you navigate away, everything is cleared, nothing stays 'subscribed', because the entire js context is disposed Commented Jul 6, 2020 at 18:37

2 Answers 2

2

Yes, it does look like a potential memory leak: on every NavigationEnd a new subscription is born, so that you have potentially unlimited number of identical observers of the same stream (and activatedRoute.firstChild.paramMap emits indefinitely). You can verify that by putting a simple console.log(new Date()) inside the subscription.

I believe switchMap is your friend here (it automatically unsubscribes from the old stream when subscribing to a new one). Sth like

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]);

BTW, don't you need to guard against this.activatedRoute.firstChild being null?

Sign up to request clarification or add additional context in comments.

1 Comment

no i don't have to guard against that. The parent component always displays a child component. I found out that i don't have to unsubscribe because it reuses the same ActivatedRoute instance under the hood. I found this out when i added pipe(first()). first() will allow ActivatedRoute to emit one value only and after that it automatically completes. That means ActivatedRoute will no longer work afterwards. So its best not to unsubscribe manually
0

No Need of unsubscribe in these cases

  1. In case of HttpClient calls because the observable emit one value (success or error) and complete automatically.

  2. In case or ActivatedRoute subscription because the Router will destroy it when the component is destroyed automatically

  3. use of Async pipe

1 Comment

the Router will destroy it when the component yes, but the app.component isen't destroyed until the browser is closed or the user navigates away from the website. That means that those subscriptions could stay active in memory until the user stops browsing the website. But i'm not sure about this hence the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.