Edit : Le problème abordé dans cette réponse a été résolu dans angular.js version 1.2.7 . $broadcastévite désormais de se propager sur des étendues non enregistrées et s'exécute aussi vite que $ emit.

Vous pouvez donc désormais:
- utiliser à
$broadcastpartir du$rootScope
- écouter en utilisant
$on le local$scope qui a besoin de connaître l'événement
Réponse originale ci-dessous
Je conseille fortement de ne pas utiliser $rootScope.$broadcast+ $scope.$onmais plutôt $rootScope.$emit+ $rootScope.$on. Le premier peut entraîner de graves problèmes de performances, comme l'a soulevé @numan. En effet, l'événement bouillonnera dans tous les domaines.
Cependant, ce dernier (en utilisant $rootScope.$emit+ $rootScope.$on) n'en souffre pas et peut donc être utilisé comme canal de communication rapide!
De la documentation angulaire de $emit:
Distribue un nom d'événement vers le haut à travers la hiérarchie d'étendue notifiant les inscrits
Puisqu'il n'y a pas de portée ci $rootScope- dessus , il n'y a pas de bouillonnement. Il est totalement sûr d'utiliser $rootScope.$emit()/ $rootScope.$on()comme EventBus.
Cependant, il existe un problème lors de son utilisation à partir de contrôleurs. Si vous vous connectez directement à $rootScope.$on()partir d'un contrôleur, vous devrez nettoyer la liaison vous-même lorsque votre section locale sera $scopedétruite. En effet, les contrôleurs (contrairement aux services) peuvent être instanciés plusieurs fois au cours de la durée de vie d'une application, ce qui entraînerait la synthèse des liaisons, créant éventuellement des fuites de mémoire partout :)
Pour annuler l' enregistrement, il suffit d' écouter sur votre $scopede » $destroyl'événement, puis appeler la fonction qui a été renvoyée par $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);
}
]);
Je dirais que ce n'est pas vraiment une chose spécifique angulaire, car cela s'applique également aux autres implémentations EventBus, que vous devez nettoyer les ressources.
Cependant, vous pouvez vous faciliter la vie dans ces cas. Par exemple, vous pouvez corriger le singe $rootScopeet lui donner un $onRootScopequi s'abonne aux événements émis sur le $rootScopemais nettoie également directement le gestionnaire lorsque le local $scopeest détruit.
La façon la plus propre de patcher le singe $rootScopepour fournir une telle $onRootScopeméthode serait de passer par un décorateur (un bloc d'exécution le fera probablement très bien aussi mais pssst, ne le dites à personne)
Pour vous assurer que la $onRootScopepropriété ne s'affiche pas de manière inattendue lors de l'énumération, $scopenous utilisons Object.defineProperty()et définissons enumerablesur false. Gardez à l'esprit que vous pourriez avoir besoin d'une cale 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;
}]);
}]);
Avec cette méthode en place, le code du contrôleur ci-dessus peut être simplifié pour:
angular
.module('MyApp')
.controller('MyController', ['$scope', function MyController($scope) {
$scope.$onRootScope('someComponent.someCrazyEvent', function(){
console.log('foo');
});
}
]);
Donc, comme résultat final de tout cela, je vous conseille fortement d'utiliser $rootScope.$emit+ $scope.$onRootScope.
Btw, j'essaie de convaincre l'équipe angulaire de résoudre le problème dans le noyau angulaire. Il y a une discussion en cours ici: https://github.com/angular/angular.js/issues/4574
Voici un jsperf qui montre combien un impact de perf $broadcastapporte à la table dans un scénario décent avec seulement 100 $scope.
http://jsperf.com/rootscope-emit-vs-rootscope-broadcast
