Does $scope.$on('$destroy', ...)'s event handler get destroyed?
Asked Answered
D

1

8

Ran across a very "down-the-rabbit-hole" Angular question today I couldn't find the answer to. From the $scope docs, you can register an event handler on "$destroy", which is called right before a scope's destruction. That way, you can deregister event handlers like so:

var deregister = $scope.$on('myCustomEvent', function () {
    // do some crazy stuff
});
$scope.$on('$destroy', function () {
    deregister();
});

However, the $scope.$on('$destroy', ...) must create its own handler. Is that automatically destroyed, or do you have to do something like the following to destroy it?

var deregister = $scope.$on('myCustomEvent', function () {
    // do some crazy stuff
});
var deregisterDestroy = $scope.$on('$destroy', function () {
    deregister();
    deregisterDestroy();
});
Depressant answered 15/12, 2014 at 21:8 Comment(4)
Yes, it is destroyed - of course if it references anything external the handler itself (and thus everything it has in its closure) won't get deallocated (just like everywhere else).Firstling
I guess the follow-up questions would be then (a) is it necessary to deregister it, and (b) if so, can you even deregister it in the way I've written above?Depressant
Naa, you just have infinite recursion - you don't need to deregister it the scope gets destroyed. I'm sure pretty soon someone with more time will make a decent and detailed answer here :)Firstling
deregister function for this listener with var deregister = $scope.$on...Gisborne
R
1

The answer is actually "maybe" depending on what you mean by it being automatically destroyed. If we look at the source for the $destroy method for scopes, we can see that while a $destroy event is broadcasted downward throughout child scopes, the actual $destroy method is never invoked on any scope but the initial one. That means that the actual cleanup and nulling out of properties never occurs on child scopes.

The reason that this doesn't leak memory is because once $destroy has been invoked on a scope, it becomes detached from the parent scope and is therefore eligible for garbage collection since it should no longer have any path to the GC Roots. This same logic applies to all child scopes since they also should have no paths to the GC Roots.

Your example is safe though; I do that myself in the same manner to clean up my own handlers when necessary and do not run into any kind of infinite loops.

Rabbitry answered 15/12, 2014 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.