98

私は持ってい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

1 に答える 1

150

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

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

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 のいくつかの興味深いパターンも確認できます。しばらく時間がかかることがわかりますが、コールバックをきれいにすることはできます。

ここに画像の説明を入力

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

于 2013-11-19T10:23:50.797 に答える