如何计算页面上的手表总数?

ty.*_*ty. 142 angularjs

在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;
})();
Run Code Online (Sandbox Code Playgroud)

Wor*_*red 217

(您可能需要更改bodyhtml或任何你把你的ng-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);
})();
Run Code Online (Sandbox Code Playgroud)
  • 感谢erilem指出这个答案错过了$isolateScope搜索,观察者可能会在他/她的回答/评论中重复.

  • 感谢Ben2307指出'body'可能需要更改.


原版的

我做了同样的事情,除了我检查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);
})();
Run Code Online (Sandbox Code Playgroud)

我也把它放在我的:

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');
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

没有打印出来,所以我猜我的更好(因为它发现了更多的手表) - 但我缺乏亲密的角度知识,以确保我的确不是解决方案集的适当子集.

  • 只是提醒一下:如果在项目中使用`$ compileProvider.debugInfoEnabled(false);`,这个片段将统计为零观察者. (10认同)
  • Bookmarklet:https://gist.github.com/clouddueling/3f134bbd98a65f9bf9b5 (4认同)
  • 我一直在尝试做类似的事情,并发现这个片段非常有用.我认为有一点值得澄清的是,'root'应设置为具有'ng-app'属性的任何元素,因为这是保留$ rootScope的地方.在我的应用程序中它的'html'标签.运行你的脚本错过了我的应用程序中的$ rootScope中的$ watchers. (2认同)
  • 这将获得附加到DOM元素的所有观察者.如果删除一个DOM元素,是否会自动清除相关的`$ scope`和`$$ watcher`,或者它们会产生性能损失? (2认同)

小智 16

我认为上面提到的方法是不准确的,因为它们将同一范围内的观察者数量加倍.这是我的书签版本:

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

它还显示了一些用于分析观察者的更多细节.


Ian*_*son 12

这是一个基于检查范围结构而放在一起的hacky解决方案.它似乎"似乎"起作用.我不确定这是多么准确,它肯定取决于一些内部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);
    };
Run Code Online (Sandbox Code Playgroud)

  • 如果我用`$ rootScope.$ new(true)`或`$ scope.$ new(true)`创建一个隔离的作用域,其中`$ scope`用于控制器,那么遍历层次结构仍然会找到该作用域.我认为这意味着原型没有连接而不是范围不在层次结构中. (3认同)

Nic*_*ele 10

有一个新的Chrome插件可以自动显示当前的总观察者和应用程序中的最后一次更改(+/-)......它非常棒.

https://chrome.google.com/webstore/detail/angular-watchers/nlmjblobloedpmkmmckeehnbfalnjnjk


boy*_*nov 9

由于我最近在应用程序中遇到了大量的观察者,我发现了一个很棒的库,名为ng-stats - https://github.com/kentcdodds/ng-stats.它具有最小的设置,并为您提供当前页面上的观察者数量+摘要周期长度.它还可以投影一个小的实时图表.


Pau*_*tte 8

在AngularJS 1.3.2中,一个countWatchers方法被添加到ngMock模块:

/**
 * @ngdoc method
 * @name $rootScope.Scope#$countWatchers
 * @module ngMock
 * @description
 * Counts all the watchers of direct and indirect child scopes of the current scope.
 *
 * The watchers of the current scope are included in the count and so are all the watchers of
 * isolate child scopes.
 *
 * @returns {number} Total number of watchers.
 */

 function countWatchers() 
   {
   var root = angular.element(document).injector().get('$rootScope');
   var count = root.$$watchers ? root.$$watchers.length : 0; // include the current scope
   var pendingChildHeads = [root.$$childHead];
   var currentScope;

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

    while (currentScope) 
      {
      count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
      pendingChildHeads.push(currentScope.$$childHead);
      currentScope = currentScope.$$nextSibling;
      }
    }

   return count;
   }

参考


Mir*_*age 7

单词的小改进像Jared的回答一样.

(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;
})();
Run Code Online (Sandbox Code Playgroud)

  • 因为你没有使用jQuery选择器,你可以使用angular.element()而不是$() (2认同)