4

I have a $rootScope.$on code on top of a controller. I noticed that everytime I load/call this controller, the $rootScope.$on listener increases meaning it will add and add and add a listener, indefinitely as you visit the controller.

I noticed it when I called it via $rootScope.$emit from another controller, the function inside the $rootScope.$on got executed several times even if it was only a single emit/broadcast.

$rootScope.$on('listen', function() {
    $scope.displayString();
});

$scope.displayString = function() {
    console.log('test'); // This display 7 times because I visit the controller 7 times
}

Is it possible to prevent it from creating another listener instance so that when there is already a listener, it won't create a new one.

devwannabe
  • 3,160
  • 8
  • 42
  • 79

1 Answers1

9

You need to deregister the event listener when you controller's scope is destroyed.

The $on function returns a deregistration function that will remove the listener when the function is invoked.

So you can set it up like this:

var deregister = $rootScope.$on('listen', function() {
    $scope.displayString();
});
$scope.$on('$destroy', deregister);

Note: this will only work if the controller's scope is actually destroyed (e.g. in a directive that is removed from the DOM or when you navigate to a different route). If that doesn't happen then you will need to work out a way of only registering the event listener once.

Sly_cardinal
  • 12,270
  • 5
  • 49
  • 50
  • 1
    I'm aware about this but won't it affect other controllers who are doing $rootScope.$emit? Will it still work? – devwannabe May 29 '15 at 05:28
  • this just de-registers the event .. nothing else. – sirrocco May 29 '15 at 05:28
  • It won't affect other controllers because each event listener registration is independent of any other. So you will only deregister that particular event listener, not all event listeners. – Sly_cardinal May 29 '15 at 06:36