0

I have this example stackblitz where I set an "id" for a component which you can create and destroy via a checkbox. Each time you create a new instance of the component, it is given an incremented id. In each component, there is an interval which console logs the component's id. I did not unsubscribe from it on destroy. I continue to see logs after the component is destroyed, as expected. What confuses me is that somehow the interval still knows which component it came from, and throws no error when referencing it's id. If the component was destroyed, how are it's properties still accessible? Does the component still exist somehow, creating a memory leak?

Caleb Bertrand
  • 410
  • 5
  • 15
  • Yes! This is a memory leak. That is why you should always unsub. You could see this as a global service where the subscription is actually stored on the observable which means it’s lifetime is not depending on the component the subscription was setup.. – MikeOne Aug 04 '21 at 16:37
  • Right, but shouldn't it throw a reference error when trying to access `this.id` on line 19? Because even if the subscription is still there, the component shouldn't be, since it was destroyed. `this` would no longer be the component. So I'm wondering if the "destroyed" component actually still exists out there, causing a memory leak. – Caleb Bertrand Aug 04 '21 at 16:46
  • Read up on ’closures’ to better understand why this is.. – MikeOne Aug 05 '21 at 07:16

2 Answers2

1

After reading more on garbage collection in JS, I realized this is sort of a trick question. There is no way to explicitly "dispose" of an object in JavaScript like in some other languages. When Angular destroys a component, it removes all it's references and the garbage collector then removes it from memory. By referencing it in a subscription callback, I am effectively telling the GC not to clean up the component yet.

So yes, angular does "clean up" a component when destroyed, in the sense that it prepares the component for removal by the GC. If that component is still referenced elsewhere, though, the GC will of course not remove it.

Caleb Bertrand
  • 410
  • 5
  • 15
  • yeah, exactly it causes memory leak if you use component a lot. one of usual errors in angular is related to subscriptions and forgetting to unsubscribe it in OnDestroy(). – Hassan Ghasemi Aug 04 '21 at 18:25
1

make sure you clean up within ngOnDestroy and you will not get this problem.

you must unsubscribe from subscriptions like so:

sub = this.myService.getObservable().subscribe();

ngOnDestroy(): void {
  this.sub.unsubscribe();
}

If you do not do this you will get the problem you are facing and subscriptions will keep emitting. This is a big gotcha for noobs to Angular.

This pattern gets annoying when a component has multiple subscriptions and there are better patterns with less code scaffolding using the RxJS operator takeUntil.

You must also ensure to call clearInterval and clearTimeout on any active intervals or timeouts when destroying a component.

danday74
  • 52,471
  • 49
  • 232
  • 283