Hi Przemysław --
This is not a performance problem for a couple reasons...
First, state change is ALREADY being communicated via $scope through isolated scope bindings and optimized for it. Where this technique is necessary is when you need to communicate a state change that is NOT on $scope, i.e. model data. How do you tell the application that something has changed in service? How do you do this without coupling classes together? This is why the observer pattern exists and essentially what we are implementing.
Secondly, we are only broadcasting to container components so that they can update their presentation state which then gets propagated to the presentation components via isolated scope. So you are in part correct, this pattern is used to communicate JUST ENOUGH so that parallel container components can make the necessary adjustments and let component $scope take over.
Thirdly, this is a similar pattern to how Redux works in that instead of
$rootScope.$broadcast, we have
store.dispatch and instead of
$scope.$on we have
store.select and observables handle the eventing for us.
Fourthly, there are specific cases for using an event bus but $rootScope is the single BEST mechanism for the job. It has already been optimized to effectively communicate with every component within the application. How (or why) could we possibly roll something more efficient on our own?
Oh... one more... in this specific case... the frequency in which we are broadcasting is negligible in terms of performance considerations. If we were hooked up to a web socket that was broadcasting 100 times a second then I may reconsider my solution for that case.