Зарегистрировать прослушиватель событий только один раз в AngularJS

Я транслирую событие с моего контроллера навигатора на другой контроллер, но если я инициализирую контроллер несколько раз (когда я иду вперед и обратно через приложение), функция, выполняемая в моем событии $on, запускает несколько раз, потому что он регистрировался несколько раз.

$rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();
});

Как предотвратить событие submitBookingDialog(), которое произойдет более одного раза?

Я нашел решение, но я не знаю, идеально ли оно.

Ответ 1

Прежде всего, вам нужно отправить событие на $rootScope? Если нет, вы можете просто зарегистрировать обработчик событий на $scope. Обработчик событий будет уничтожен всякий раз, когда будет уничтожена область вашего контроллера. Затем вы отправляете событие через $scope.$emit или $scope.$broadcast в зависимости от вашей иерархии контроллера.

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

var offSubmitBookingDialog = $rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();
});

$scope.$on('$destroy', function() {
    // Call the deregistration function when the scope is destroyed
    offSubmitBookingDialog();
});

Ответ 2

Это похоже на меня:

var removeListener = $rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();

    // Remove listener
    removeListener();
});

Ответ 3

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

https://github.com/callmehiphop/hey

Ответ 4

Для потомков я закончил это:

.run(function($rootScope) {
    $rootScope.once = function(e, func) {
        var unhook = this.$on(e, function() {
            unhook();
            func.apply(this, arguments);
        });
    };
})

Потому что мне все время нужно было делать это в нескольких местах, это просто стало чище.
С помощью этого модуля приложения вы можете просто вызвать once вместо $on:

$rootScope.once('submitBookingDialog', function() {
    submitBookingDialog();
});

Ответ 5

Возможно, вы отказались от подписки на событие с уничтожением контроллера

var removeSubmitBookingDialog = $rootScope.$on('submitBookingDialog',submitBookingDialog);
$scope.$on("$destroy", removeSubmitBookingDialog);