Destroyed component's properties are accessible via subscription - how?

529 Views Asked by At

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?

2

There are 2 best solutions below

1
On BEST ANSWER

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.

0
On

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.