0

My Angular application is fairly big already and I am using the rootScope to communicate between directives and controllers.

Directive 1
scope.$root.$broadcast('some:event');

Controller 1
$rootScope.$on('some:event', function() { I get called multiple times :( });
$scope.$on('some:event', function() { I am not getting called at all :( });

For some reason, my listeners get called multiple times (2x to be exact). I have the feeling that somewhere, I built in a second rootScope or something. I am currently debugging my app, but it is like finding the needle in the haystack.

This thread tries to solve a similar problem: AngularJs broadcast repeating execution too many times. It suggests to use $scope only which does not work for me in my particular case. The broadcasted events never reach the listeners.

My question would be if someone has an idea why this could happen? Maybe I am doing a silly mistake I am not aware of. Catching an event twice I only sent once does sound wrong.

Thanks in advance

Community
  • 1
  • 1
pabera
  • 1,042
  • 1
  • 13
  • 22
  • You must use the $scope instead of $rootScope to use the broadcasted events .... can you show us the reason why you can't use $scope.on()??? – Bhojendra Rauniyar Jan 24 '15 at 10:22
  • 1
    Why can't you follow the suggestion in the linked SO question? You should broadcast from `$rootScope` (if you are trying to reach everyone), but listen with `$scope.$on` – New Dev Jan 24 '15 at 10:22
  • I just modified my question a bit: It actually works for controllers, the problem occurs for the communication between directives and controllers. As I called out, the solution in the example I linked does not work for me .. – pabera Jan 24 '15 at 10:31
  • 1
    Is it possible that the event is fired only once, but you attach the listener multiple times? Maybe you have two instances of the controller? – Thomas Jan 24 '15 at 10:32
  • Are you doing right?? scope.$root.$broadcast('some:event'); – Bhojendra Rauniyar Jan 24 '15 at 10:34
  • 1
    `You must use the $scope instead of $rootScope to use the broadcasted events` this is false. And if you are trying to reach everyone `$rootScope.$emit` and `$rootScope.$on` is better for performance. My first guess is what Thomas mentioned. – tasseKATT Jan 24 '15 at 10:34
  • 1
    Note that when using `$rootScope.$on` you need to manually unregister when the controller's scope is destroyed, or you will end up with a new listener every time the controller is initialized (same goes for directives). – tasseKATT Jan 24 '15 at 10:38
  • It was indeed the case: I found two controllers. Must have been a relict from some earlier development. Still I learned more about what is important around rootScope events. Thanks – pabera Jan 24 '15 at 10:44

2 Answers2

6

use

$rootScope.$emit('some:event') ;

because it goes upwards and rootscope ist the top level

use

var myListener = $rootScope.$on('some:event', function (event, data) { });

$scope.$on('$destroy', myListener); 

dont forgot to unregister on destroy and u have a bus communication on the same level

Edit: To your problem: maybe some other listener prevent it from bubbling further like this:.

 $scope.$on('some:event', function (event, data) {
    event.stopPropagation();
 });

And the reason why your listener receive mulltible times could be that u send multible times. test with sending a timestring with your event and see if it is the same

Here is a fiddle with my Eventbus factory i use http://jsfiddle.net/navqtaoj/2/ Sometimes the good old observerpattern works also fine:http://jsfiddle.net/b742qdpz/ if it is to much overhead to watch a value in a service

micha
  • 1,238
  • 10
  • 7
4

Tighten Your Module & Scope

Many times, when you're experiencing multiple dispatches of an event -- or more specifically, when you've multiple Handlers being invoked then your modules need to utilize locality more.

By locality I mean, try not to use globals as much as possible. This can (and usually does) occur, usually, when you're listening/firing events off of $rootScope instead of $scope -- which is more local.

What Angular Does (In a Nutshell)

Angular has a special way of event-subscription-binding which differes based upon scope.

If an event is subscribed to using a controller, which uses a perishable scope, then Angular automatically unsubscribes to each event when the controller closes.

However, when subscribing using $rootScope, Angular will not insist on detaching these subscription-bindings. So...

TL;DR

Every time you load a view -- effectively constructing a new controller -- you are undoubtedly wiring up another listener for each subscription.

Hope this helps!

Community
  • 1
  • 1
Cody
  • 9,785
  • 4
  • 61
  • 46