web-dev-qa-db-ja.com

解決されなかった約束はメモリリークの原因になりますか?

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ライフサイクルの管理方法に関するアドバイスはありますか?

83
Umut Benzer

まあ、私はあなたがそれを割り当てられたままにすることを強制するので、それへの明示的な参照を保持しないと仮定しています。

私が考えることができる最も簡単なテストは、実際には多くの約束を割り当て、それらを解決しないことです:

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のプロミスを割り当てるために必要なメモリを蓄積してから、全体に15メガバイト未満で「そこにとどまる」 JSFIddleページ

enter image description here

反対側から $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);

enter image description here

したがって、初期割り当ての後-それも同様に処理できるようです:)

彼の最後の例をさらに数分間実行すると、GCの興味深いパターンを見ることができます。しばらく時間がかかることがわかりますが、コールバックをクリーンアップできます。

enter image description here

つまり、少なくとも最新のブラウザーでは、外部参照がなければ、未解決の約束について心配する必要はありません。

141