source

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

lovecheck 2023. 3. 8. 21:16
반응형

스코프가 파괴되었을 때 각도 $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어레이가 비워지고 스코프가 스코프 계층에서 삭제됩니다.

의 삭제watcherunregister 함수가 수행하는 모든 작업은 어레이에서 수행됩니다.

$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();
    });
}

요소 파괴 이벤트를 사용하여 스코프를 파괴합니다.

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

반응형