IT이야기

스코프가 파괴 될 때 각도 $ watch를 제거

cyworld 2021. 4. 28. 20:34
반응형

스코프가 파괴 될 때 각도 $ watch를 제거해야합니까?


현재 파괴 된 범위에서 브로드 캐스트 구독을 지우지 않을 때 엄청난 메모리 누수가 발견 된 프로젝트를 진행 중입니다. 다음 코드는이 문제를 해결했습니다.

var onFooEventBroadcast = $rootScope.$on('fooEvent', doSomething);

scope.$on('$destroy', function() {
    //remove the broadcast subscription when scope is destroyed
    onFooEventBroadcast();
});

이 관행을 시계에도 사용해야합니까? 아래 코드 예 :

var onFooChanged = scope.$watch('foo', doSomething);

scope.$on('$destroy', function() {
    //stop watching when scope is destroyed
    onFooChanged();
});

아니요, $$watchers스코프가 파괴되면 효과적으로 제거되므로 제거 할 필요가 없습니다 .

Angular의 소스 코드 (v1.2.21)에서 Scope$destroy방법 :

$destroy: function() {
    ...
    if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
    if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
    if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
    if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
    ...
    this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];
    ...

따라서 $$watchers배열이 비워지고 범위가 범위 계층에서 제거됩니다.

watcher배열에서를 제거하는 것은 어쨌든 등록 해제 기능이 수행하는 모든 것입니다.

$watch: function(watchExp, listener, objectEquality) {
    ...
    return function deregisterWatch() {
        arrayRemove(array, watcher);
        lastDirtyWatch = null;
    };
}

따라서 $$watchers"수동" 등록을 취소 할 필요가 없습니다 .


그래도 이벤트 리스너 등록을 취소해야합니다 (게시물에서 올바르게 언급했듯이)!

참고 : 다른 범위에 등록 된 리스너 만 등록 취소하면됩니다. 소멸되는 범위에 등록 된 리스너를 등록 취소 할 필요가 없습니다.
예 :

// You MUST unregister these
$rootScope.$on(...);
$scope.$parent.$on(...);

// You DON'T HAVE to unregister this
$scope.$on(...)

( 지시 를 위해 @John에게 감사합니다 )

또한 소멸되는 범위보다 오래 지속되는 요소에서 이벤트 리스너를 등록 취소해야합니다. 예를 들어 지시문이있는 경우 상위 노드 또는에 리스너를 등록한 <body>다음 등록을 취소해야합니다.
다시 말하지만, 소멸되는 요소에 등록 된 리스너를 제거 할 필요가 없습니다.


원래 질문과는 관련이 없지만 이제 $destroyed파괴되는 요소에 전달 되는 이벤트 있으므로 여기에 연결할 수 있습니다 (사용 사례에 적합한 경우).

link: function postLink(scope, elem) {
  doStuff();
  elem.on('$destroy', cleanUp);
}

@gkalpak 의 답변 을 추가하고 싶습니다 .

내가 작업하고 있던 응용 프로그램은 감시자가있는 지시문을 대체하여 메모리 누수를 일으켰습니다. 지시문은 jQuery를 사용하여 대체 된 다음 준수되었습니다.

수정하기 위해 다음 링크 기능을 추가했습니다.

link: function (scope, elem, attrs) {
    elem.on('$destroy', function () {
        scope.$destroy();
    });
}

요소 destroy 이벤트를 사용하여 범위를 차례로 삭제합니다.

참조 URL : https://stackoverflow.com/questions/25113884/should-angular-watch-be-removed-when-scope-destroyed

반응형