4

如何从服务内部清理 $rootScope.$on 事件订阅?

我有一个工厂,它正在我的 AngularJS 应用程序的不同控制器中初始化,其中声明了 $rootScope.$on 事件订阅。我的问题是,当控制器被销毁时,事件没有被清理。我已经阅读并发现使用控制器和指令可以在 $destroy 上设置 $watch 进行清理,但是对于服务呢?你如何清理服务?

这是我的问题的基本 Plunker: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();
});
4

1 回答 1

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);
});
于 2014-11-12T20:15:03.310 回答