약속을 해결하지 않으면 메모리 누수가 발생합니까?


92

나는 Promise . 필요한 경우 AJAX 요청을 취소하기 위해 만들었습니다. 하지만 해당 AJAX를 취소 할 필요가 없기 때문에 문제를 해결하지 않았고 AJAX가 성공적으로 완료되었습니다.

단순화 된 스 니펫 :

var defer = $q.defer();
$http({url: 'example.com/some/api', timeout: defer.promise}).success(function(data) {
    // do something
});

// Never defer.resolve() because I don't need to cancel that ajax. What happens to this promise after request?

그런 약속을 해결하지 않아서 메모리 누수가 발생합니까? Promise라이프 사이클 을 관리하는 방법에 대한 조언이 있습니까?


4
"해결되지 않은"약속은 여전히 ​​"거부"될 수 있습니다. 당신이 찾고 있던 단어는 "unfulfilled"였습니다.
Steven Vachon

$ http는 'timeout'인수에 전달 된 promise에 관계없이 클라이언트가 서버에 도달 할 수없는 경우 HTTP 요청이 시간 초과 (또는 오류 응답을 생성)하므로 흥미로운 예입니다.
ryanwebjackson

답변:


145

글쎄, 나는 당신이 그것에 대한 명시적인 참조를 유지하지 않는다고 가정합니다.

내가 생각할 수있는 가장 간단한 테스트는 실제로 많은 약속을 할당하고 해결하지 않는 것입니다.

var $q = angular.injector(["ng"]).get("$q");
setInterval(function () {
    for (var i = 0; i < 100; i++) {
        var $d = $q.defer();
        $d.promise;
    }
}, 10);

그리고 힙 자체를 관찰합니다. Chrome 프로파일 링 도구에서 볼 수 있듯이, 이것은 100 개의 promise를 할당하는 데 필요한 메모리를 축적 한 다음 전체 JSFIddle 페이지에 대해 15 메가 바이트 미만으로 "계속 유지" 합니다.

여기에 이미지 설명 입력

다른 쪽에서는 소스 코드를 보면$q

전역 지점에서 특정 약속에 대한 참조가없고 약속에서 콜백에 대한 참조 만 있음을 알 수 있습니다. 코드는 매우 읽기 쉽고 명확합니다. 그러나 콜백에서 프라 미스에 대한 참조가있는 경우 어떻게하는지 살펴 보겠습니다.

var $q = angular.injector(["ng"]).get("$q");
console.log($q);
setInterval(function () {
    for (var i = 0; i < 10; i++) {
        var $d = $q.defer();
        (function ($d) { // loop closure thing
            $d.promise.then(function () {
                console.log($d);
            });
        })($d);
    }
}, 10);

여기에 이미지 설명 입력

따라서 초기 할당 후-그것도 처리 할 수있는 것 같습니다. :)

그의 마지막 예제를 몇 분 더 실행하면 GC의 흥미로운 패턴을 볼 수도 있습니다. 시간이 걸리는 것을 알 수 있지만 콜백을 정리할 수 있습니다.

여기에 이미지 설명 입력

간단히 말해서-적어도 최신 브라우저에서는 외부 참조가없는 한 해결되지 않은 약속에 대해 걱정할 필요가 없습니다.


8
이것은 약속이 해결하는 데 너무 오래 걸리지 만 결국 해결 될 경우 GC가 될 위험에 처한다는 것을 의미하지 않습니까?
w.brian

6
@ w.brian 어딘가에 할당하지 않는 한-예를 들어 변수에 : var b = $http.get(...)또는 콜백을 추가합니다. 그것은 또한 그것에 대한 참조를 가지고 있습니다. 무언가가 그것을 해결한다면 (당신이 말했듯이-해결하기에 너무 길다는 것은 여전히 ​​해결을 의미합니다)-그것에 대한 참조가 있어야합니다. 그래서 그렇습니다 – 그것은 GC'd가 아닙니다
Benjamin Gruenbaum

3
알았어, 그렇게 생각 했어. 그래서 질문은 "결코 해결 된 약속이 메모리 누수를 유발하지 않습니까?"입니다. 콜백이 프라 미스에 전달되는 일반적인 사용 사례에 대한 대답은 '예'입니다. 귀하의 답변에있는이 줄은 다음과 같이 모순되는 것 같습니다. "마지막 예제를 몇 분 더 실행하면 몇 가지 흥미로운 GC 패턴을 볼 수 있습니다. 시간이 걸리는 것을 알 수 있지만 콜백을 정리할 수 있습니다. " 내가 현학적이고 까다 롭다면 죄송합니다. 나는 이것을 이해하도록 노력하고 있습니다.
w.brian

1
그건 말이 안되는 것 같아요. 내가 100.000을 만들었다면 console.log ()가 몇 줄을 약속합니다. 갑자기 마술로 해결되면 그 100.000이 그 줄을 기록하기를 바랍니다. 아니면 브라우저가이는 것을 알 수 있다는 말을 결코 도 있기 때문에, 해결되지 않는 I 그래서 어떻게 이제까지 사실 일 수 -도 실제 브라우저가 (아무 영향이)에 대한 참조가? (흠, 난 그 사실이 될 수 볼 수 있습니다)
odinho - Velmont

9
이 주석에는 일부 진실이 있으며 일부는 오해의 소지가 있으므로 명확히하겠습니다. 핸들러가 첨부 된 약속 은 가비지 수집에 적합 수 있습니다. 다음 하나 라도 참인 경우 Promise는 활성 상태로 유지됩니다 (GC 자격이 아님) . / 해결 / 거부하는 데 사용하는 기능). 이 외에 Promise는 GC에 적합합니다. (아무도 약속이 없으며 아무도 그 상태를 변경할 수 없다면, 무슨 목적 어쨌든, 더 이상입니까?)
cdhowie
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.