Change the way $rootScope.$broadcast works internally #8461
Description
Hi, $rootScope.$broadcast/$scope.$on
is almost perfect. It make us able to use $scope.$on
for global events, this is perfect since we can handle local and global events the same way and it takes care of deleting listener (freeing memory) for us when $scope
is destroyed.
Compared to it $rootScope.$emit/$rootScope.$on
is faster but requires us to manually clear the callback to avoid leaking memory in listener.
$rootScope.$broadcast
on the contrary is a little slow, cause it traverses all active scopes to find listeners to be triggered. Is it really necessary?
Why can't we solve the same problem in a different way?
Let's try to use a map in $rootScope:
Something like:
$rootScope.
evtScopesMap = {
evt: {scope1ref: true, scope2ref: true}
}
Listening:
function $on(evt, cb) {
// ...
$rootScope.
evtScopesMap[evt] = thisScope;
}
Broadcasting:
function broadcast(evt) {
Object.keys(this.evtScopesMap[evt]).forEach(function(scope){
// Iterate scope.$$listeners and $emit;
})
}
Cleaning up
scope.destroy = function(){
// Iterate scope.$$listeners
// forEach event this scope is bound to:
delete $rootScope.evtScopesMap[evt][thisScope];
}
This should make $broadcast time constant in finding scopes at a small cost of a having an hashmap with scope references in $rootScope (cost in memory is linear to active scopes count).
I apologize if I misunderstood something here.
Thank you anyway