[angularjs] angularJS에서 브로드 캐스트 이벤트를 구독 취소하는 방법 $ on을 통해 등록 된 기능을 제거하는 방법
$ on 함수를 사용하여 청취자를 $ broadcast 이벤트에 등록했습니다.
$scope.$on("onViewUpdated", this.callMe);
특정 비즈니스 규칙에 따라이 리스너의 등록을 취소하고 싶습니다. 그러나 내 문제는 일단 등록되면 등록을 취소 할 수 없다는 것입니다.
AngularJS에 특정 리스너의 등록을 해제하는 방법이 있습니까? 이 이벤트를 등록 취소하는 $ on과 같은 방법은 $ off 일 수 있습니다. 비즈니스 로직을 바탕으로 말할 수 있습니다.
$scope.$off("onViewUpdated", this.callMe);
이 함수는 누군가 “onViewUpdated”이벤트를 브로드 캐스트 할 때 호출이 중지됩니다.
감사
편집 : 다른 기능에서 리스너를 등록 취소하고 싶습니다. 내가 등록한 기능이 아닙니다.
답변
반환 된 함수를 저장하고 이벤트에서 구독을 취소하려면 호출해야합니다.
var deregisterListener = $scope.$on("onViewUpdated", callMe);
deregisterListener (); // this will deregister that listener
이것은 소스 코드에서 찾을 수 있습니다 🙂 적어도 1.0.4. 전체 코드는 짧기 때문에 게시하겠습니다.
/**
* @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;
};
},
또한 docs를 참조하십시오 .
답변
대부분의 답글을 보면 지나치게 복잡해 보입니다. Angular에는 등록 해제 메커니즘이 내장되어 있습니다.
다음에 의해 반환 된 등록 해제 기능을$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');
답변
코드를 디버깅 한 후 “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의 답변에 있습니다! 그러나 다른 범위에서 리스너를 등록 취소하고 동시에 등록 취소 기능의 참조를 유지하기 위해 로컬 변수를 작성하지 않으려는 경우. 가능한 해결책입니다.
답변
@ LiviuT의 답변은 훌륭하지만 다른 $ scope 또는 함수에서 처리기의 분해 기능에 다시 액세스하는 방법을 궁금해하는 사람들이 많이 있습니다. @ Рустем Мусабеков의 답변은 훌륭하게 작동하지만 관용적이지는 않습니다. (그리고 개인 구현 세부 사항에 의존해야하며 언제든지 변경 될 수 있습니다.) 그리고 더 복잡해집니다 …
여기서 쉬운 해답 offCallMeFn
은 핸들러 자체에서 테어 다운 함수 ( 예를 들어)에 대한 참조를 수행 한 다음 조건에 따라 호출하는 것입니다. 아마도 당신이 $ broadcast 또는 $ emit 이벤트에 포함하는 인수 일 것입니다. 따라서 처리자는 원할 때마다 원하는 곳에서 자신의 파괴의 씨앗을 들고 다닐 수 있습니다. 이렇게 :
// 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
하고 자살 미션을 완료하자마자 실행하십시오 . - 클로저 변수에 대한 참조를 가지고 있다고 가정하면 원래 범위가 올바르게 파괴되고 가비지 수집 될지 궁금합니다. 메모리 문제가 되려면 백만 가지를 사용해야하지만 궁금합니다. 누군가 통찰력이 있으면 공유하십시오.
답변
구성 요소가 제거 될 때 청취자를 구독 취소하려면 후크를 등록하십시오.
$scope.$on('$destroy', function () {
delete $rootScope.$$listeners["youreventname"];
});