Как я могу отменить регистрацию широковещательного события в rootscope в AngularJS?


У меня есть следующие:

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
    })

   }]);

Это мое понимание, что мне нужно отменить регистрацию событий. Может кто-нибудь сказать мне, как я мог бы код / сделать это?

4 64

4 ответа:

если вы не отмените регистрацию события, вы получите утечку памяти, так как функция, которую вы передаете $on не будет очищаться (поскольку ссылка на него все еще существует). Что еще более важно, любые переменные, которые ссылаются на функции в своей области, также будут пропущены. Это приведет к тому, что ваша функция будет вызываться несколько раз, если ваш контроллер будет создан/уничтожен несколько раз в приложении. К счастью, AngularJS предоставляет несколько полезных методов, чтобы избежать утечек памяти и нежелательных поведение:

  • The $on метод возвращает функцию, которая может быть вызвана для отмены регистрации прослушивателя событий. Вы захотите сохранить свою функцию дерегистрации в качестве переменной для последующего использования:var cleanUpFunc = $scope.$on('yourevent', ...); смотрите документацию для $on: http://docs.angularjs.org/api/ng.$rootScope. Scope#$on

  • всякий раз, когда область очищается в угловой (т. е. контроллер разрушается) a $destroy события в этой области. Вы можно зарегистрироваться на $scope ' s $destroy событие и вызвать ваш cleanUpFunc от этого.

вы можете связать эти две полезные вещи вместе, чтобы очистить ваши подписки правильно. Я собрал пример этого:http://plnkr.co/edit/HGK9W0VJGip6fhYQQBCg?p=preview. если вы закомментируете строку cleanUpFunc(); а затем нажмите кнопку переключения и сделать вещи несколько раз, вы заметите, что наш обработчик событий вызывается несколько раз, что на самом деле не так желанный.

теперь, после всего этого, чтобы ваша конкретная ситуация вела себя правильно, просто измените свой код в QuestionsStatusController2 следующим образом:

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();
    });

   }]);

по телефону cleanUpFunc() на $destroy, ваш прослушиватель событий для action2@QuestionStatusController1 событие будет не подписано, и вы больше не будете утечка памяти, когда ваш контроллер будет очищен.

зарегистрируйте слушателя на локальном $scope, а не $rootScope и слушатель будет уничтожен автоматически при снятии контроллера.

так публиковать

// EXAMPLE PUBLISHER
angular.module('test').controller('CtrlPublish', ['$rootScope', '$scope',
function ($rootScope, $scope) {

  $rootScope.$broadcast('topic', 'message');

}]);

и подписаться

// EXAMPLE SUBSCRIBER
angular.module('test').controller('ctrlSubscribe', ['$scope',
function ($scope) {

  $scope.$on('topic', function (event, arg) { 
    $scope.receiver = 'got your ' + arg;
  });

}]);

Plunker

здесь исходный код о логике снятия с учета. Вы можете сделать:

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

или вызовите функцию отмены регистрации, возвращенную из $on()

var deregistration = $rootScope.$on('action2@QuestionStatusController1', function () {
    deregistration();
})
$scope.$on('saveCancelLeadInfo', function (event, args) {

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

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

        } });