Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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();
});
like image 460
jdotjdot Avatar asked Dec 15 '14 21:12

jdotjdot


1 Answers

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.

like image 90
dherman Avatar answered Sep 19 '22 21:09

dherman