144

JavaScript で、ページ全体の角度のある時計の数を数える方法はありますか?

私たちはBatarangを使用していますが、必ずしも私たちのニーズに合うとは限りません。私たちのアプリケーションは大きいので、自動テストを使用して、ウォッチ カウントが増えすぎていないかどうかを確認したいと考えています。

コントローラーごとに時計をカウントすることも役立ちます。

編集:これが私の試みです。クラス ng-scope ですべての時計をカウントします。

(function () {
    var elts = document.getElementsByClassName('ng-scope');
    var watches = [];
    var visited_ids = {};
    for (var i=0; i < elts.length; i++) {
       var scope = angular.element(elts[i]).scope();
       if (scope.$id in visited_ids) 
         continue;
       visited_ids[scope.$id] = true;
       watches.push.apply(watches, scope.$$watchers);
    }
    return watches.length;
})();
4

12 に答える 12

220

(またはどこに置くかを変更する必要がある場合がありbodyます)htmlng-app

(function () { 
    var root = angular.element(document.getElementsByTagName('body'));

    var watchers = [];

    var f = function (element) {
        angular.forEach(['$scope', '$isolateScope'], function (scopeProperty) { 
            if (element.data() && element.data().hasOwnProperty(scopeProperty)) {
                angular.forEach(element.data()[scopeProperty].$$watchers, function (watcher) {
                    watchers.push(watcher);
                });
            }
        });

        angular.forEach(element.children(), function (childElement) {
            f(angular.element(childElement));
        });
    };

    f(root);

    // Remove duplicate watchers
    var watchersWithoutDuplicates = [];
    angular.forEach(watchers, function(item) {
        if(watchersWithoutDuplicates.indexOf(item) < 0) {
             watchersWithoutDuplicates.push(item);
        }
    });

    console.log(watchersWithoutDuplicates.length);
})();
  • $isolateScopeこの回答が検索されておらず、ウォッチャーが回答/コメントで重複している可能性があることを指摘してくれた erilem に感謝します。

  • 'body'を変更する必要があるかもしれないことを指摘してくれた Ben2307 に感謝します。


オリジナル

クラスではなく HTML 要素のデータ属性をチェックしたことを除いて、同じことをしました。私はここであなたのものを走らせました:

http://fluid.ie/

そして83になりました.私は私のものを実行し、121を得ました.

(function () { 
    var root = $(document.getElementsByTagName('body'));
    var watchers = [];

    var f = function (element) {
        if (element.data().hasOwnProperty('$scope')) {
            angular.forEach(element.data().$scope.$$watchers, function (watcher) {
                watchers.push(watcher);
            });
        }

        angular.forEach(element.children(), function (childElement) {
            f($(childElement));
        });
    };

    f(root);

    console.log(watchers.length);
})();

私もこれを私の中に入れました:

for (var i = 0; i < watchers.length; i++) {
    for (var j = 0; j < watchers.length; j++) {
        if (i !== j && watchers[i] === watchers[j]) {
            console.log('here');
        }
    }
}

何も印刷されていないので、私のほうが優れていると思います(より多くの時計が見つかったという点で)-しかし、私のものがソリューションセットの適切なサブセットではないことを確認するには、角度に関する詳細な知識がありません。

于 2013-08-30T06:55:04.377 に答える
16

言及されたアプローチは、同じスコープのウォッチャーを2倍にカウントするため、不正確だと思います。ブックマークレットの私のバージョンは次のとおりです。

https://gist.github.com/DTFAgus/3966db108a578f2eb00d

また、ウォッチャーを分析するための詳細もいくつか示しています。

于 2014-08-13T07:16:37.850 に答える
13

これは、スコープ構造の検査に基づいてまとめたハッキーなソリューションです。うまくいくように「見える」。これがどれほど正確かはわかりませんが、内部 API に依存していることは間違いありません。angularjs 1.0.5 を使用しています。

    $rootScope.countWatchers = function () {
        var q = [$rootScope], watchers = 0, scope;
        while (q.length > 0) {
            scope = q.pop();
            if (scope.$$watchers) {
                watchers += scope.$$watchers.length;
            }
            if (scope.$$childHead) {
                q.push(scope.$$childHead);
            }
            if (scope.$$nextSibling) {
                q.push(scope.$$nextSibling);
            }
        }
        window.console.log(watchers);
    };
于 2013-08-30T18:47:23.747 に答える
9

Words Like Jared's answer のマイナーな改善。

(function () {
    var root = $(document.getElementsByTagName('body'));
    var watchers = 0;

    var f = function (element) {
        if (element.data().hasOwnProperty('$scope')) {
            watchers += (element.data().$scope.$$watchers || []).length;
        }

        angular.forEach(element.children(), function (childElement) {
            f($(childElement));
        });
    };

    f(root);

    return watchers;
})();
于 2014-05-05T10:45:37.483 に答える
8

AngularJS 1.3.2 では、countWatchersメソッドが ngMock モジュールに追加されました。

/**
 * @ngdoc メソッド
 * @name $rootScope.Scope#$countWatchers
 * @モジュール ngMock
 * @説明
 * 現在のスコープの直接および間接の子スコープのすべてのウォッチャーをカウントします。
 *
 * 現在のスコープのウォッチャーはカウントに含まれ、すべてのウォッチャーもカウントに含まれます
 * 子スコープを分離します。
 *
 * @returns {number} ウォッチャーの総数。
 */

  関数 countWatchers()
   {
   var root = angular.element(document).injector().get('$rootScope');
   var カウント = root.$$watchers ? root.$$watchers.length : 0; // 現在のスコープを含める
   var pendingChildHeads = [root.$$childHead];
   var currentScope;

   while (pendingChildHeads.length)
    {
    currentScope = pendingChildHeads.shift();

    while (現在のスコープ)
      {
      count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
      pendingChildHeads.push(currentScope.$$childHead);
      currentScope = currentScope.$$nextSibling;
      }
    }

   リターンカウント;
   }

参考文献

于 2015-06-22T18:50:55.310 に答える
4

$digest以下のコードは、関数自体から直接取得しました。もちろん、おそらくdocument.body下部にあるアプリケーション要素セレクター ( ) を更新する必要があります。

(function ($rootScope) {
    var watchers, length, target, next, count = 0;

    var current = target = $rootScope;

    do {
        if ((watchers = current.$$watchers)) {
            count += watchers.length;
        }

        if (!(next = (current.$$childHead ||
                (current !== target && current.$$nextSibling)))) {
            while (current !== target && !(next = current.$$nextSibling)) {
                current = current.$parent;
            }
        }
    } while ((current = next));

    return count;
})(angular.element(document.body).injector().get('$rootScope'));

于 2015-05-27T08:47:06.657 に答える
1

これは私が使用する機能です:

/**
 * @fileoverview This script provides a window.countWatchers function that
 * the number of Angular watchers in the page.
 *
 * You can do `countWatchers()` in a console to know the current number of
 * watchers.
 *
 * To display the number of watchers every 5 seconds in the console:
 *
 * setInterval(function(){console.log(countWatchers())}, 5000);
 */
(function () {

  var root = angular.element(document.getElementsByTagName('body'));

  var countWatchers_ = function(element, scopes, count) {
    var scope;
    scope = element.data().$scope;
    if (scope && !(scope.$id in scopes)) {
      scopes[scope.$id] = true;
      if (scope.$$watchers) {
        count += scope.$$watchers.length;
      }
    }
    scope = element.data().$isolateScope;
    if (scope && !(scope.$id in scopes)) {
      scopes[scope.$id] = true;
      if (scope.$$watchers) {
        count += scope.$$watchers.length;
      }
    }
    angular.forEach(element.children(), function (child) {
      count = countWatchers_(angular.element(child), scopes, count);
    });
    return count;
  };

  window.countWatchers = function() {
    return countWatchers_(root, {}, 0);
  };

})();

この関数はハッシュを使用して、同じスコープを複数回カウントしないようにします。

于 2014-11-28T17:57:46.107 に答える