3

Как очистить $ rootScope. $ От подписки на события изнутри службы?

У меня есть фабрика, которая инициализируется в разных контроллерах моего приложения AngularJS, где объявляется подписка $ rootScope. $ On event. Моя проблема в том, что когда контроллер уничтожен, событие не очищается. Я сделал чтение и обнаружил, что с контроллерами и директивами вы можете настроить $ watch на $ destroy для очистки, но как насчет сервисов? Как вы очищаете услуги?

Вот базовый плунжер моей проблемы: http://plnkr.co/edit/dY3BVW. Нажмите кнопку «создать ребенка» на кучу времени, чтобы инициализировать дочерний контроллер, который будет инициализировать фабрику с помощью $ rootScope. $ On. Когда консоль браузера откроется, когда вы нажмете «трансляцию», вы увидите, что запущена подписка на события, событие после того, как дочерние контроллеры были уничтожены.

Отрывок из Plunker:

// setup rootScope on in Factory and create multiple instances 
// to show that event subscriptions are not cleaned up 
// TODO: how do you cleanup in factory? 
app.factory('HelloWorldFactory', function($rootScope) { 

    // setup event subscription on initialization 
    function HelloWorldFactory() { 
    console.log('init helloWorldFactory'); 

    var rootScopeOn = $rootScope.$on('test', function() { 
     console.log('test sub', Math.random()); 
    }); 
    } 

    return HelloWorldFactory; 
}); 

// child ctrl will init a new factory instance 
app.controller('ChildCtrl', function($scope, HelloWorldFactory) { 
    $scope.name = 'Child'; 

    var helloWolrdFactory = new HelloWorldFactory(); 
}); 
+0

Хотелось бы также знать, что оставшиеся слушатели событий могут вызвать какое-то действительно неприятное поведение. – twDuke

+0

@twDuke Я в основном завернул $ на событие подписки в логическом условном выражении, а затем только инициализировался один раз, установив переменную isLoaded в true на первом проходе. – wbeange

ответ

4

Вы можете убить стража перед созданием нового события. Переменная rootScopeOn останется нетронутой после создания новых контроллеров, поэтому вы можете убить ее каждый раз, когда вы ее снова инициализируете.

app.factory('HelloWorldFactory', function($rootScope) { 

    var rootScopeOn; 

    // setup event subscription on initialization 
    function HelloWorldFactory() { 
    console.log('init helloWorldFactory'); 
    if (typeof rootScopeOn === 'function') { 
     rootScopeOn(); 
    } 

    rootScopeOn = $rootScope.$on('test', function() { 
     console.log('test sub', Math.random()); 
    }); 
    } 

    return HelloWorldFactory; 
}); 

// child ctrl will init a new factory instance 
app.controller('ChildCtrl', function($scope, HelloWorldFactory) { 
    $scope.name = 'Child'; 

    var helloWolrdFactory = new HelloWorldFactory($scope); 
}); 
+0

Это в правильном направлении, однако у меня есть несколько контроллеров, и каждый из них инициализирует собственный экземпляр Factory. Таким образом, чтобы управлять только одной переменной rootScopeOn и несколькими экземплярами, она работает сама по себе и удаляет все, кроме последней инициализированной фабрики. – wbeange

+0

Я изменил Plunker, чтобы сделать это более ясным. Кроме того, чтобы сделать вещи более запутанными для меня, эта служба на самом деле вызвана из прототипически унаследованного класса класса модели в разных классах моделей детей, и поэтому различение между ними на родительском уровне, на котором вызывается фабрика, может быть жестким. – wbeange

Смежные вопросы