I was wondering two things, in the context of angularJS event handling.
After reading documentation on angular $on, $broadcast and $emit as well as native DOM event flow I think I understand in which order event handlers will be trigger in different scopes. The problem is when several handlers listen in the same scope ($rootScope for example) from various places (Controllers vs Services for example).
To illustrate the problem I have put together a jsfiddle with one controller and two services, all communicating through $rootScope http://jsfiddle.net/Z84tX/
Thanks
Very good question.
Event handlers are executed in order of initialization.
I haven't really thought about this before, because my handlers never needed to know which one run first, but by the look of you fiddle I can see that the handlers are called in the same order in which they are initialized.
In you fiddle you have a controller controllerA
which depends on two services, ServiceA
and ServiceB
:
myModule .controller('ControllerA', [ '$scope', '$rootScope', 'ServiceA', 'ServiceB', function($scope, $rootScope, ServiceA, ServiceB) {...} ] );
Both services and the controller define an event listener.
Now, all dependencies need to be resolved before being injected, which means that both services will be initialized before being injected into the controller. Thus, handlers defined in the services will be called first, because service factories are initialized before controller.
Then, you may also observe that the services are initialized in order they are injected. So ServiceA
is initialized before ServiceB
because they are injected in that order into the controller. If you changed their order inside the controller signature you'll see that their initilization order is also changed (ServiceB
comes before ServiceA
).
So, after the services are initialized, the controller gets initialized as well, and with it, the event handler defined within.
So, the end result is, on $broadcast, the handlers will be executed in this order: ServiceA
handler, ServiceB
handler, ControllerA
handler.
It's a bit messy (and I wouldn't recommend it) to go about this route, but wanted to provide an alternative incase you are unable to ensure serviceB will be initialized before serviceA and you absolutely need serviceB's listener to be executed first.
You can manipulate the $rootScope.$$listeners
array to put serviceB's listener first.
Something like this would work when adding the listener to $rootScope
on serviceB:
var listener, listenersArray; $rootScope.$on('$stateChangeStart', someFunction); listenersArray = $rootScope.$$listeners.$stateChangeStart; listener = listenersArray[listenersArray.length - 1]; listenersArray.splice(listenersArray.length - 1, 1); listenersArray.unshift(listener);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With