There are Routines in our lives which become simply tortures for us. There are tons of them in my life. For example I hate to pack my sport suite when I go to the gym, and unpack it again, when I come at home. Definitely this task is just emptiness in time and space for me. Probably the reason is the human nature itsel. We are annoyed doing things which are pointless for us and think that somehow It can be avoided.
The same story goes for resource cleaning in any type of application. Almost all Modern programming languages already support Garbace Collection, which cleans up useless resources by itself. But sometimes we have to tell the engine explicitly to clean it up, otherwise We will have a memory leak. I know what’s the first thing floated in your head; subscribe/unsubscribe pattern. Yeah this is definitely another torture routine in my life, calling unsubscribe, for avoiding a memory leak. Unfortunately there are more than that, like disposing socket connection, or removing timers etc. We have to trigger their cleaning process somewhere.
One of The best place to cleanup our resources is
ngOnDestroy callback inside our Component. Angular gives us a lifecycle hook, and guides us to use this callback in order to clean our resources If it’s not cleared automatically.
The place where we first meet with
ngOnDestroy callback is in the Angular docs at the Hooking into the component lifecycle section. and there is fairly good explanation what, when and how this callback is called.
Cleanup just before Angular destroys the directive or component. Unsubscribe Observables and detach event handlers to avoid memory leaks. See details in Cleaning up on instance destruction in this document. Called immediately before Angular destroys the directive or component.
So with a bit help of logical reasoning, we can assume that when Component or Directive, gets destroyed it will call our callback. But there are also, some core elements inside Angular like service or pipe. what about them? is there any handy method that will be called if any of them will be destroyed?. if we look at their documentation, there is no single notation about them. So a person (like me) would think that, there is no callback for that, and I have to call my cleanup method explicitly, when I want to. But as it turns out it’s not the case
Finding out the truth the hard way
Couple months ago, I was digging into the open-source library, and saw that one of it’s service extended
OnDestroy interface and therefore implemented
ngOnDestroy callback. At first I thought it was because of naming convention, so the creators of this library agreed to name a method
ngOnDestroy if it’s for cleanup process. The surprise was that each of those methods were never called inside the App itself.
After having a donkey face, I knew that I was fooled for a long long time. So I went to the ngOnDestroy Docs API. and find the following description
A lifecycle hook that is called when a directive, pipe, or service is destroyed. Use for any custom cleanup that needs to occur when the instance is destroyed
As it turns out,
ngOnDestroy works not only on Component or Directive, it is also usable for Service and Pipe. I was angry and happy at the same time, because after all I would have one less routine in my life afterwards.
We know when component is removed from the view, it get’s destroyed and thus
ngOnDestroy is called, but what about service?
When the service will be destroyed?
It is totally dependent, In which scope you attach that service. There are 3 different scopes
if you add inside Component,Directive providers array, it will be destroyed whenever one of them is removed.
If you add it inside Module providers array, it will be destroyed whenever the module is removed, for example on route-change
If you add it in root, It will be destroyed when you are closing the window( by that time nobody cares cleanup process, because it is done by the V8 engine)
It’s totally up to you in which scope you attach a service. whenever it will be destroyed it will call
This is a simple example, how to use
ngOnDestroy inside the service, it is pretty straightforward and exactly the same as component implementation.
We have a
TimerService that’s upon initialization emits an event every 1 second.
and here we have
TimerComponent that catches the emittion and renders it to the view
TimerService to the providers array, so it is component scoped, meaning that whenever this component will be destroyed, it will destroy a service instance also.
So whenever we remove the component from the view, it will call
ngOnDestroy method, and cleanup
(This example is only for demonstration purpose, it could be implemented much better way…)