Редагувати : Проблема, адресована у цій відповіді, була вирішена у angular.js версії 1.2.7 . $broadcastтепер уникає барботажу над незареєстрованими областями і працює так само швидко, як $ emit.

Отже, тепер ви можете:
- використання
$broadcastвід$rootScope
- слухайте, використовуючи
$on місцевих,$scope які повинні знати про подію
Оригінальний відповідь нижче
Я настійно раджу не використовувати $rootScope.$broadcast+, $scope.$onа скоріше $rootScope.$emit+ $rootScope.$on. Перший може спричинити серйозні проблеми з роботою, які піднімає @numan. Це тому, що подія занепаде всіма сферами.
Однак останній (використовуючи $rootScope.$emit+ $rootScope.$on) від цього не страждає і тому може використовуватися як швидкий канал зв'язку!
З кутової документації $emit:
Відправляє ім'я події вгору за допомогою ієрархії діапазону, що сповіщає про зареєстрованих
Оскільки немає сфери вгорі $rootScope, не виникає барботаж. Це абсолютно безпечно для використання $rootScope.$emit()/ $rootScope.$on()як EventBus.
Однак є одна ґутка при використанні її зсередини контролерів. Якщо ви безпосередньо зв’язуєтеся $rootScope.$on()зсередини контролера, вам доведеться очистити прив'язку самостійно, коли ваш локальний файл $scopeбуде знищений. Це тому, що контролери (на відміну від сервісів) можуть отримувати екземпляри кілька разів протягом життя програми, що призведе до прив'язки, підсумовуючи зрештою, створюючи витоки пам'яті в усьому місці :)
Щоб скасувати реєстрацію, просто прослухайте подію вашої $scope, $destroyа потім зателефонуйте до функції, яку повернув $rootScope.$on.
angular
.module('MyApp')
.controller('MyController', ['$scope', '$rootScope', function MyController($scope, $rootScope) {
var unbind = $rootScope.$on('someComponent.someCrazyEvent', function(){
console.log('foo');
});
$scope.$on('$destroy', unbind);
}
]);
Я б сказав, що це насправді не кутова особлива річ, як це стосується й інших реалізацій EventBus, що вам доведеться очищати ресурси.
Однак ви можете полегшити своє життя у цих випадках. Наприклад, ви можете виправити патч мавпи $rootScopeі дати йому $onRootScopeпідписку на події, що випромінюються, $rootScopeале також безпосередньо очищає обробник, коли локальний $scopeзнищується.
Найчистішим способом промацування мавпи $rootScopeнадати такий $onRootScopeметод було б через декоратор (блок запуску, ймовірно, зробить це добре, але pssst, не кажіть нікому)
Для того, щоб переконатися , що $onRootScopeвластивість не проявляється несподіваним при перерахуванні більш $scopeми використовуємо Object.defineProperty()і встановити enumerableна false. Майте на увазі, що вам може знадобитися прокладка ES5.
angular
.module('MyApp')
.config(['$provide', function($provide){
$provide.decorator('$rootScope', ['$delegate', function($delegate){
Object.defineProperty($delegate.constructor.prototype, '$onRootScope', {
value: function(name, listener){
var unsubscribe = $delegate.$on(name, listener);
this.$on('$destroy', unsubscribe);
return unsubscribe;
},
enumerable: false
});
return $delegate;
}]);
}]);
За допомогою цього методу замість коду контролера зверху можна спростити:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
Тож як кінцевий результат усього цього я настійно раджу використовувати $rootScope.$emit+ $scope.$onRootScope.
До речі, я намагаюсь переконати команду кутових вирішити проблему в кутовому ядрі. Тут триває дискусія: https://github.com/angular/angular.js/isissue/4574
Ось jsperf, який показує, скільки впливів на парфюмер $broadcastприносить на стіл у пристойному сценарії всього з 100 $scope.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
