Edycja : Problem rozwiązany w tej odpowiedzi został rozwiązany w wersji angular.js w wersji 1.2.7 . $broadcastteraz unika bulgotania się nad niezarejestrowanymi zakresami i działa tak szybko, jak $ emit.

Teraz możesz:
- użyj
$broadcastz$rootScope
- słuchaj za pomocą
$on lokalnego,$scope który musi wiedzieć o wydarzeniu
Oryginalna odpowiedź poniżej
Radzę nie używać $rootScope.$broadcast+, $scope.$onale raczej $rootScope.$emit+ $rootScope.$on. To pierwsze może powodować poważne problemy z wydajnością, o czym wspomniał @numan. Dzieje się tak, ponieważ wydarzenie rozbije się na wszystkie zakresy.
Jednak to ostatnie (użycie $rootScope.$emit+ $rootScope.$on) nie cierpi z tego powodu i dlatego może być używane jako szybki kanał komunikacji!
Z dokumentacji kątowej $emit:
Wysyła nazwę zdarzenia w górę poprzez hierarchię zasięgu, powiadamiając zarejestrowanego
Ponieważ nie ma powyższego zakresu $rootScope, nie ma miejsca na bulgotanie. Używanie $rootScope.$emit()/ $rootScope.$on()jako EventBus jest całkowicie bezpieczne .
Jest jednak jedna gotcha, gdy używasz go z poziomu kontrolerów. Jeśli łączysz się bezpośrednio $rootScope.$on()z kontrolerem, musisz samodzielnie usunąć powiązanie, gdy lokalny $scopezostanie zniszczony. Wynika to z faktu, że kontrolery (w przeciwieństwie do usług) mogą być wielokrotnie tworzone przez cały czas istnienia aplikacji, co powoduje zsumowanie powiązań, co ostatecznie spowoduje przeciek pamięci w całym miejscu :)
Aby wyrejestrować, tylko słuchać na swojej $scope„s $destroyzdarzenia, a następnie wywołać funkcję, który został zwrócony przez $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);
}
]);
Powiedziałbym, że tak naprawdę nie jest to kwestia specyficzna pod kątem, ponieważ dotyczy to również innych implementacji EventBus, że musisz oczyścić zasoby.
W takich przypadkach możesz jednak ułatwić sobie życie. Na przykład, możesz małpować łatkę $rootScopei dać jej $onRootScopesubskrypcję zdarzeń emitowanych na, $rootScopeale także bezpośrednio czyści program obsługi, gdy lokalny $scopezostanie zniszczony.
Najczystszym sposobem na załatanie małpy w $rootScopecelu zapewnienia takiej $onRootScopemetody byłoby zastosowanie dekoratora (blok uruchamiania prawdopodobnie zrobi to dobrze, ale pssst, nie mów nikomu)
Aby upewnić się, że $onRootScopewłaściwość nie pojawi się nieoczekiwanie podczas wyliczania ponad $scope, używamy Object.defineProperty()i ustawiamy enumerablena false. Pamiętaj, że możesz potrzebować podkładki 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;
}]);
}]);
Dzięki tej metodzie kod kontrolera z góry można uprościć w celu:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
Dlatego jako ostateczny wynik tego wszystkiego radzę użyć $rootScope.$emit+ $scope.$onRootScope.
Przy okazji, staram się przekonać zespół kątowy do rozwiązania problemu w rdzeniu kątowym. Trwa dyskusja tutaj: https://github.com/angular/angular.js/issues/4574
Oto jsperf, który pokazuje, jak duży wpływ $broadcastna stół przynosi porządny scenariusz w zaledwie 100 $scope.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
