如何在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.)
两个想法:
- 这是一个运行一次处理程序的一个很好的公式。 只要完成自杀任务,就放弃条件并运行
selfDestruct
。 - 我想知道原始范围是否会被正确销毁和垃圾收集,因为你正在引用被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 })