6

ビューを更新する Angular Js の非常に標準的なメソッドの例を考えてみましょう。

$scope.fetchResults = function() {
    // Some local variable that will cause creation of closure
    var hugeData = serviceX.getMilionRecords();

    // Any call to any resource with success and error handlers.
    $http({
        method: "GET",
        url: "/rest-api/bulk-operation-x",
        params: { someParam: hugeData.length }

    }).success( function () {
        var length = hugeData.length;
        $scope.reportToUser("Success, that was " + length + " records being processed!";

    }).error( function () {
        var length = hugeData.length;
        $scope.reportToUser("Something went wrong while processing " + length + " records... :-(";
    });
};

これはもちろん架空の例ですが、 AJAX コールバック内からのローカル変数の再利用として説明できるパターンをうまく示しています。

もちろん両方のハンドラー (successと) で、コールバック ハンドラーから直接参照されるerrorクロージャーを作成しています。hugeData

私の質問は次のとおりです。AJAX 呼び出しの結果は成功または失敗のいずれかしかあり得ないため、このコードを再利用すると時間の経過とともにメモリ リークが発生しますか? 私は「はい」と答えますが、ローカル テストでこれを確実に証明することはできませんでした。

もっと経験豊富なグルにこれを説明してもらいたいです。Angular を日常的に使用している方からの返信をお待ちしておりますが、jquery からの返信も大歓迎です。

4

1 に答える 1

4

$http()呼び出しの結果 (または にアクセスできるオブジェクトや関数hugeData) を の外側のスコープに返すとすぐに、メモリ リークが発生しますfetchResults

あなたのコードでは、大きなものは外部に直接公開されず、呼び出しfetchResultsの結果は、$http()成功または失敗するまで存続し、対応するコールバックを呼び出し、最終的に GC されます。

洞察については、http: //jibbering.com/faq/notes/closures/#clIdResを参照してください。

@ŁukaszBachman が観察しているように、これはメモリ リークがないことを保証するものではありません。ビッグ オブジェクトへのダングリング リファレンス、またはスコープ内のビッグ オブジェクトを含むコールバックへのダングリング リファレンスは、問題を引き起こします。

$qそれでは、実装を確認しましょう($httpは に基づいています$q)。

https://github.com/angular/angular.js/blob/master/src/ng/q.js#L191を確認するresolve()と、deferredのメソッドが最初に登録済みコールバックのリストを変数にコピーしていることがわかりますメソッドにローカル:

var callbacks = pending;

その後、(レベルpendingで定義された)外部を無効にします。defer

pending = undefined;

次に、次のティックでコールバックを実行します。コールバックの引数自体が据え置き型 (実行にさらに遅延が追加される) である可能性があるという事実によって事態が複雑になる可能性がありますが、せいぜい無限ループに入る可能性があります。(そして、それは面白くありません!)。幸運にもループに入らなかった場合、ある時点でコールバック配列が使い果たされ、コールバック リストへの参照がまったくないため、GC で使用できるようになります。

しかし。

無理にやるとうまくいかないことがあります。

コールバック内で arguments.callee を使用できます。

キーボードにビールを投げることもできます。

窓から飛び降りると、1階に住んでいないと怪我をする恐れがあります。

ハッピー EcmaScripting!

于 2013-06-04T11:42:54.303 に答える