如何在angularJS中取消订阅广播事件。 如何删除通过$ on注册的函数

我已经使用$ on函数将侦听器注册到$ broadcast事件

$scope.$on("onViewUpdated", this.callMe); 

我想根据特定的业务规则取消注册此侦听器。 但我的问题是,一旦注册,我无法取消注册。

AngularJS有什么方法可以取消注册一个特定的监听器吗? 像$这样的方法注销这个事件,可能是$closures。 所以基于我可以说的商业逻辑

  $scope.$off("onViewUpdated", this.callMe); 

当有人播放“onViewUpdated”事件时该函数停止被调用。

谢谢

编辑 :我想从另一个function取消注册监听器。 不是我注册的function。

您需要存储返回的函数并调用它来取消订阅事件。

 var deregisterListener = $scope.$on("onViewUpdated", callMe); deregisterListener (); // this will deregister that listener 

这是在源代码:)至less在1.0.4中find。 我只是发布完整的代码,因为它很短

 /** * @param {string} name Event name to listen on. * @param {function(event)} listener Function to call when the event is emitted. * @returns {function()} Returns a deregistration function for this listener. */ $on: function(name, listener) { var namedListeners = this.$$listeners[name]; if (!namedListeners) { this.$$listeners[name] = namedListeners = []; } namedListeners.push(listener); return function() { namedListeners[indexOf(namedListeners, listener)] = null; }; }, 

另外,请参阅文档 。

大部分的答复,他们似乎过于复杂。 Angularbuild立了取消注册的机制。

使用由$on返回的注销函数 :

 // Register and get a handle to the listener var listener = $scope.$on('someMessage', function () { $log.log("Message received"); }); // Unregister $scope.$on('$destroy', function () { $log.log("Unregistering listener"); listener(); }); 

这段代码适用于我:

 $rootScope.$$listeners.nameOfYourEvent=[]; 

编辑:正确的方法是在@ LiviuT的答案!

你总是可以扩展Angular的范围,让你去除这样的监听器:

 //A little hack to add an $off() method to $scopes. (function () { var injector = angular.injector(['ng']), rootScope = injector.get('$rootScope'); rootScope.constructor.prototype.$off = function(eventName, fn) { if(this.$$listeners) { var eventArr = this.$$listeners[eventName]; if(eventArr) { for(var i = 0; i < eventArr.length; i++) { if(eventArr[i] === fn) { eventArr.splice(i, 1); } } } } } }()); 

这是如何工作的:

  function myEvent() { alert('test'); } $scope.$on('test', myEvent); $scope.$broadcast('test'); $scope.$off('test', myEvent); $scope.$broadcast('test'); 

这是一个在行动中的重击者

在debugging代码之后,我创build了自己的函数,就像“blesh”的答案一样。 所以这就是我所做的

 MyModule = angular.module('FIT', []) .run(function ($rootScope) { // Custom $off function to un-register the listener. $rootScope.$off = function (name, listener) { var namedListeners = this.$$listeners[name]; if (namedListeners) { // Loop through the array of named listeners and remove them from the array. for (var i = 0; i < namedListeners.length; i++) { if (namedListeners[i] === listener) { return namedListeners.splice(i, 1); } } } } }); 

所以通过将我的函数附加到$ rootscope,现在它可用于我的所有控制器。

并在我的代码我正在做

 $scope.$off("onViewUpdated", callMe); 

谢谢

编辑:AngularJS的方式是在@ LiviuT的答案! 但是,如果要在另一个作用域中取消注册侦听器,并且同时希望避免创build局部variables以保留取消注册function的引用。 这是一个可能的解决scheme。

@ LiviuT的答案很棒,但似乎让很多人想知道如何从另一个$ scope或者函数中重新访问这个处理程序的拆卸函数,如果你想从非创build的地方销毁它。 @РустемМусабеков的答案很好,但不是很习惯。 (并依赖于什么应该是一个私人实现的细节,这可能会改变任何时候。)从那里,它变得更加复杂…

我认为这里的简单答案是简单地在处理程序本身中引用拆除函数(在他的示例中是offCallMeFn ),然后根据某些条件调用它; 也许是你在广播或放射事件中包含的一个参数。 因此,处理者可以随时随地撕下自己,随时随地摧毁自己的种子。 像这样:

 // Creation of our handler: var tearDownFunc = $rootScope.$on('demo-event', function(event, booleanParam) { var selfDestruct = tearDownFunc; if (booleanParam === false) { console.log('This is the routine handler here. I can do your normal handling-type stuff.') } if (booleanParam === true) { console.log("5... 4... 3... 2... 1...") selfDestruct(); } }); // These two functions are purely for demonstration window.trigger = function(booleanArg) { $scope.$emit('demo-event', booleanArg); } window.check = function() { // shows us where Angular is stashing our handlers, while they exist console.log($rootScope.$$listeners['demo-event']) }; // Interactive Demo: >> trigger(false); // "This is the routine handler here. I can do your normal handling-type stuff." >> check(); // [function] (So, there's a handler registered at this point.) >> trigger(true); // "5... 4... 3... 2... 1..." >> check(); // [null] (No more handler.) >> trigger(false); // undefined (He's dead, Jim.) 

两个想法:

  1. 这是一个运行一次处理程序的一个很好的公式。 只要完成自杀任务,就放弃条件并运行selfDestruct
  2. 我想知道原始范围是否会被正确销毁和垃圾收集,因为你正在引用被closures的variables。 你不得不使用其中的一百万甚至是内存问题,但我很好奇。 如果有人有任何见解,请分享。

'$ on'本身返回注销的函数

  var unregister= $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options) { alert('state changing'); }); 

你可以调用unregister()函数来取消注册该监听器

一种方法是一旦你完成了就摧毁听众。

 var removeListener = $scope.$on('navBarRight-ready', function () { $rootScope.$broadcast('workerProfile-display', $scope.worker) removeListener(); //destroy the listener })