Comment puis-je désinscrire un événement de diffusion à rootscope dans AngularJS?

J’ai ce qui suit:

angular.module('test') .controller('QuestionsStatusController1', ['$rootScope', '$scope', '$resource', '$state', function ($rootScope, $scope, $resource, $state) { $scope.action2 = function() { $rootScope.$broadcast('action2@QuestionStatusController1'); } }]); angular.module('test') .controller('QuestionsStatusController2', ['$rootScope', '$scope', '$resource', '$state', function ($rootScope, $scope, $resource, $state) { $rootScope.$on('action2@QuestionStatusController1', function { //write your listener here }) }]); 

Je crois comprendre que je dois annuler l’enregistrement de l’événement d’écoute. Est-ce que quelqu’un peut me dire comment je pourrais coder / faire ceci?

Si vous ne désenregistrez pas l’événement, vous obtiendrez une fuite de mémoire, car la fonction que vous transmettez à $on ne sera pas nettoyée (car une référence existe toujours). Plus important encore, toutes les variables dont les références de fonction ont une scope sont également divulguées. Cela provoquera l’appel de votre fonction plusieurs fois si votre contrôleur est créé / détruit plusieurs fois dans une application. Heureusement, AngularJS propose quelques méthodes utiles pour éviter les memory leaks et les comportements indésirables:

  • La méthode $on renvoie une fonction qui peut être appelée pour désinscrire l’écouteur d’événement. Vous voudrez enregistrer votre fonction de var cleanUpFunc = $scope.$on('yourevent', ...); tant que variable pour une utilisation ultérieure: var cleanUpFunc = $scope.$on('yourevent', ...); Voir la documentation pour $on : http://docs.angularjs.org/api/ng.$rootScope.Scope#$on

  • Chaque fois qu’une scope est nettoyée dans Angular (c’est-à-dire qu’un contrôleur est détruit), un événement $destroy est déclenché sur cette scope. Vous pouvez vous inscrire à l’événement $destroy et appeler votre cleanUpFunc partir de cela.

Vous pouvez associer ces deux éléments utiles pour nettoyer correctement vos abonnements. J’ai mis en place un exemple de ceci: http://plnkr.co/edit/HGK9W0VJGip6fhYQQBCg?p=preview . Si vous commentez la ligne cleanUpFunc(); puis appuyez sur le bouton bascule et faites plusieurs fois, vous remarquerez que notre gestionnaire d’événement est appelé plusieurs fois, ce qui n’est pas vraiment souhaité.

Maintenant, après tout cela, pour que votre situation spécifique se comporte correctement, changez simplement votre code dans QuestionsStatusController2 comme suit:

 angular.module('test') .controller('QuestionsStatusController2', ['$rootScope', '$scope', '$resource', '$state', function ($rootScope, $scope, $resource, $state) { var cleanUpFunc = $rootScope.$on('action2@QuestionStatusController1', function { //write your listener here }); $scope.$on('$destroy', function() { cleanUpFunc(); }); }]); 

En appelant cleanUpFunc() dans $destroy , votre écouteur d’événement pour l’événement action2@QuestionStatusController1 sera non abonné et vous ne perdrez plus de mémoire lorsque votre contrôleur sera nettoyé.

Enregistrez l’écouteur sur la $scope locale $scope , pas sur $rootScope , et l’ écouteur sera automatiquement détruit lorsque le contrôleur sera supprimé.

Donc pour publier

 // EXAMPLE PUBLISHER angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope', function ($rootScope, $scope) { $rootScope.$broadcast('topic', 'message'); }]); 

Et abonnez-vous

 // EXAMPLE SUBSCRIBER angular.module('test').controller('ctrlSubscribe', ['$scope', function ($scope) { $scope.$on('topic', function (event, arg) { $scope.receiver = 'got your ' + arg; }); }]); 

Plunker

Voici le code source de la logique de désenregistrement. Tu peux faire:

 $rootScope.$on('action2@QuestionStatusController1', function () { $rootScope.$$listeners['action2@QuestionStatusController1'] = []; }) 

ou appelez la fonction de désenregistrement renvoyée par $on()

 var deregistration = $rootScope.$on('action2@QuestionStatusController1', function () { deregistration(); }) 
 $scope.$on('saveCancelLeadInfo', function (event, args) { if ($scope.$$listenerCount["saveCancelLeadInfo"] > 1) { $scope.$$listenerCount["saveCancelLeadInfo"] = 0; } });