Issue
I've been told that using angular events can be expensive (I've been unable to verify this)
Any calls to $broadcast
and $on
should be 'wrapped' with a factory or service to inject into their corresponding components to preserve performance?
Again I'd rather use $on
and listen directly to the events being fired rather than creating a factory that in essence is just going to register functions to call when it receives the event - lets call this a dispatcher.
Please note that it's not just one component (directives) listening to 'some-event' there will be a variety of components listening to this event.
Example dispatcher:
angular.module('app').factory('dispatcher', ['$rootScope', function ($rootScope) {
var registeredFns = [ ];
$rootScope.$on('some-event', function (evt, msg) {
_.each(registeredFns, function (fn) {
fn.apply(null, msg);
});
});
return {
onSomeEvent: function (fn) {
registeredFns.push(fn);
}
};
});
And inject it where I need it - maybe a directive, maybe a controller where ever it doesn't matter.
Solution
They're not expensive at all... but they're potentially expensive if they're misused (like anything else in life - this sounds like the start of a good joke!)
It's important to understand what's actually happening in here, and the code is actually pretty straightforward. If you call $emit(), it just does a for()
loop across the array of registered listeners and calls each one. It does this on the scope you first call it on, and then walks "up" each parent until it hits $rootScope.
There's a little bit of extra code to handle things like stopPropagation, but otherwise that's it.
$broadcast does something similar, but in the opposite direction: it does this for() loop but then goes through every child scope. That's a super important difference, because if you do a $rootScope.$broadcast()
and you have a lot of ngRepeats and directives floating around, you could be doing a huge amount more work than you expect - even if none of those scopes listen for this event, Angular still has to go through them all to figure that out.
Your fastest use-case if you want to do the fastest possible test in jsPerf or similar would be to use $rootScope.$emit()
and $rootScope.$on()
. That will give you a single-scope test for basic message passing and you can go from there.
Answered By - Chad Robinson
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.