Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Change the way $rootScope.$broadcast works internally #8461

Closed
mcasimir opened this issue Aug 3, 2014 · 6 comments
Closed

Change the way $rootScope.$broadcast works internally #8461

mcasimir opened this issue Aug 3, 2014 · 6 comments

Comments

@mcasimir
Copy link

mcasimir commented Aug 3, 2014

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

@petebacondarwin
Copy link
Contributor

We recently improved the performance of $rootScope.$broadcast considerable. See #5507
Have you looked at those?

It would be worth looking at the cost of these broadcasts with some real numbers before spending too much time trying to improve the performance. Do you have a concrete use case where $broadcast is too slow for you?

@petebacondarwin petebacondarwin added this to the Backlog milestone Aug 4, 2014
@btford btford removed the gh: issue label Aug 20, 2014
@lgalfaso
Copy link
Contributor

lgalfaso commented Jan 8, 2015

looks like #8461 (comment) is spot on. If there is anything else remaining, please feel free to reopen the issue

@lgalfaso lgalfaso closed this as completed Jan 8, 2015
@michaelhunziker
Copy link

@petebacondarwin Hi Pete, just to be clear. Could you verify the following statements?

  • Fire a global event in a controller or service: $rootScope.$broadcast('MY_EVENT');
  • Listen to a global event in a controller: $scope.$on('MY_EVENT', myEventHandler);
    • Question: Should we use $scope.$on or $rootScope.$on here?
  • 3 Listen to a global event in a service: $rootScope.$on('MY_EVENT', myEventHandler);
    • Since we do not have a $scope in a service we need to do $rootScope.on(...)

As far as I understand I don't have to worry about any memory leak handling (deleting listeners when $scope is destroyed) with the above code, right?

@lgalfaso
Copy link
Contributor

A good rule of thumb is that you should attach to the scope that follows
the same lifecycle. This is, a controller to $scope (using $on or
$onRootScope) and services to $rootScope, but avoid attaching in the later
case if possible.

@michaelhunziker
Copy link

@lgalfaso Thanks for your reply. What exactly do you mean with $onRootScope? As far as I understand this method does not really exist? (#5507 -> statement by Igor Minar: "In the light of all the performance improvements we've done since this issue was created, does it still make sense to add an api like $onRootScope?")

@lgalfaso
Copy link
Contributor

What exactly do you mean with $onRootScope?

Sorry, my mistake, just remove onRootScope from the previous message.
Anyhow, the general rule applies too, even without this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants