Comment annuler l'enregistrement d'un événement de diffusion sur rootscope dans AngularJS?


62

Je donne les résultats suivants:

angular.module('test') 
    .controller('QuestionsStatusController1', 
    ['$rootScope', '$scope', '$resource', '$state', 
    function ($rootScope, $scope, $resource, $state) { 

     $scope.action2 = function() { 
      $rootScope.$broadcast('[email protected]'); 
     } 

    }]); 

angular.module('test') 
    .controller('QuestionsStatusController2', 
    ['$rootScope', '$scope', '$resource', '$state', 
    function ($rootScope, $scope, $resource, $state) { 

    $rootScope.$on('[email protected]', function { 
     //write your listener here 
    }) 

    }]); 

Je crois savoir que je dois désenregistrer l'événement d'écoute. Quelqu'un peut-il me dire comment je pourrais coder/faire cela?

+1

double possible de [Comment résilier votre abonnement à un événement de diffusion en AngularJS. Comment supprimer la fonction enregistrée via $ on] (http://stackoverflow.com/questions/14898296/how-to-unsubscribe-to-a-broadcast-event-in-angularjs-how-to-remove-function-reg) 17 sept.. 132013-09-17 21:15:50

+2

Lorsque vous diffusez à partir de $ rootScope, tout le problème est que vous n'avez plus besoin d'écouter le $ rootScope - il se propage à toutes les portées de votre système. Mon conseil est - utilisez $ scope. $ On afin que si votre portée est détruite ou remplacée par le changement d'itinéraire, elle désenregistrera automatiquement ses propres écouteurs. Sinon, vous aurez des fermetures persistantes qui s'exécuteront même si les portées d'écoute qui utilisent l'événement ont disparu depuis longtemps 18 déc.. 142014-12-18 21:06:17

  0

@neaumusic, Great ..! Votre astuce m'a aidé .. :) 24 nov.. 162016-11-24 10:29:01

146

Si vous n'êtes pas désenregistrer l'événement, vous obtiendrez une fuite de mémoire, comme la fonction que vous passez à $on ne sera pas nettoyé (comme une référence à elle existe toujours). Plus important encore, toutes les variables qui fonctionnent dans sa portée seront également divulguées. Votre fonction sera appelée plusieurs fois si votre contrôleur est créé/détruit plusieurs fois dans une application. Heureusement, AngularJS fournit quelques méthodes utiles pour éviter les fuites de mémoire et les comportements indésirables:

  • La méthode $on retourne une fonction qui peut être appelée à désenregistrer l'écouteur d'événement. Vous voulez enregistrer votre fonction de registre comme une variable pour une utilisation ultérieure: var cleanUpFunc = $scope.$on('yourevent', ...); Consultez la documentation $on: http://docs.angularjs.org/api/ng.$rootScope.Scope#$on

  • Chaque fois qu'un champ est nettoyée dans angulaire (c.-à-un contrôleur est détruit) un événement $destroy est tiré sur ce champ. Vous pouvez vous inscrire à l'événement $destroy de $scope et appelez le cleanUpFunc.

Vous pouvez lier ces deux éléments utiles ensemble 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 cliquez plusieurs fois sur le bouton bascule et faire des choses, vous remarquerez que notre gestionnaire d'événements est appelé plusieurs fois, ce qui n'est pas vraiment souhaité.

Maintenant, après tout cela, pour rendre votre situation spécifique correctement se comporter, il suffit de changer votre code QuestionsStatusController2 à ce qui suit:

angular.module('test') 
    .controller('QuestionsStatusController2', 
    ['$rootScope', '$scope', '$resource', '$state', 
    function ($rootScope, $scope, $resource, $state) { 

    var cleanUpFunc = $rootScope.$on('[email protected]', function { 
     //write your listener here 
    }); 

    $scope.$on('$destroy', function() { 
     cleanUpFunc(); 
    }); 

    }]); 

En appelant cleanUpFunc() dans $destroy, votre écouteur d'événement pour l'événement [email protected] sera ne vous désabonnez pas et vous ne perdrez plus de mémoire lorsque votre contrôleur sera nettoyé.

  0

Aurait un bus d'événement abstraite dans un service d'éviter le besoin de tout le temps? 06 déc.. 132013-12-06 12:00:11

+3

Super utile. Je me demandais pourquoi mes auditeurs tiraient plusieurs fois. Cela l'a réparé. 10 févr.. 142014-02-10 21:10:14

  0

Pour une raison quelconque, l'événement $ destroy ne démarre pas. Des idées pour lesquelles cela se produirait? 09 sept.. 142014-09-09 22:08:32

+6

Utilisez '$ scope. $ On ('actio ...', pas $ $ rootScope. $ On (' actio ... '.Pas besoin de' cleanUpFunc' Voir la réponse ci-dessous 26 sept.. 142014-09-26 13:37:05

+2

@ Polaris878 pouvez-vous mettre à jour le lien? à plnkr? il est cassé 07 nov.. 142014-11-07 20:54:20

  0

Je vous remercie beaucoup 09 juin. 172017-06-09 17:01:21


16

Voici la source code à propos de la logique de désinscription. Vous pouvez faire:

$rootScope.$on('[email protected]', function() { 
    $rootScope.$$listeners['[email protected]'] = []; 
}) 

ou appeler la fonction désenregistrement retour de $on()

var deregistration = $rootScope.$on('[email protected]', function() { 
    deregistration(); 
}) 

40

Enregistrez l'écouteur sur le $scope local, pas le $rootScope et le listener will be destroyed automatically lorsque le contrôleur est 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

+1

Je voudrais souligner que cette réponse s'applique effectivement à la plupart des cas, y compris les OP où nous voulons radier un auditeur. Angulaire le fera automatiquement pour nous lorsque la portée est détruite si nous attachons l'écouteur à la portée locale, ce qui signifie aussi que l'événement devra être '$ broadcast-ed' versus' $ emit-ed' pour qu'il atteigne la portée, mais cela me semble également plus intuitif. 09 févr.. 152015-02-09 06:32:33


0
$scope.$on('saveCancelLeadInfo', function (event, args) { 

     if ($scope.$$listenerCount["saveCancelLeadInfo"] > 1) { 

      $scope.$$listenerCount["saveCancelLeadInfo"] = 0; 

     } }); 
  0

Bien que ce code peut répondre à la question, en fournissant contexte supplémentaire concernant _why_ et/ou _how_ il répond la question permettrait d'améliorer de manière significative son long terme va Lue. S'il vous plaît [modifier] votre réponse pour ajouter quelques explications. 30 mai. 162016-05-30 13:00:12

+1

Les propriétés préfixées «$$» doivent être évitées 17 mars. 172017-03-17 09:28:12