Как подсчитать общее количество часов на странице?
есть ли способ в JavaScript подсчитать количество угловых часов на всей странице?
мы используем:бэтаранг, но это не всегда подходит. Наше приложение является большим, и мы заинтересованы в использовании автоматизированных тестов, чтобы проверить, если количество часов идет слишком много.
было бы также полезно подсчитывать часы на основе каждого контроллера.
Edit: вот моя попытка. Он считает часы во всем с классом НГ-сфера.
(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;
})();
11 ответов:
(возможно, вам придется изменить
bodyдоhtmlили куда бы вы ни положили свой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); })();
спасибо erilem за указание на этот ответ не хватало
$isolateScopeпоиск и наблюдатели потенциально дублируются в его/ее ответе / комментарии.спасибо Ben2307 за указание на то, что
'body'возможно, потребуется изменить.
Оригинал
я сделал то же самое кроме того, я проверил атрибуты HTML-элемента, а не его класс. Я побежал Ваш здесь:
и получил 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'); } } }и ничего не распечатано, поэтому я предполагаю, что мой лучше (в том, что он нашел больше часов) - но мне не хватает интимных угловых знаний, чтобы знать наверняка, что мой не является правильным подмножеством решения набор.
Я думаю, что упомянутые подходы неточны, поскольку они считают наблюдателей в одном и том же объеме двойным. Вот моя версия букмарклета:
https://gist.github.com/DTFagus/3966db108a578f2eb00d
Он также показывает некоторые более подробные данные для анализа наблюдателей.
вот хакерское решение, которое я собрал на основе проверки структур области. Это "кажется" работает. Я не уверен, насколько это точно, и это определенно зависит от некоторых внутренних 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); };
есть новый плагин chrome, который автоматически показывает текущее общее количество наблюдателей и последнее изменение (+/-) в любое время в вашем приложении... это просто потрясающе.
https://chrome.google.com/webstore/detail/angular-watchers/nlmjblobloedpmkmmckeehnbfalnjnjk
Как я недавно боролся с большим количеством наблюдателей в моем приложении, тоже я обнаружил большую библиотеку, называется ng-stats - https://github.com/kentcdodds/ng-stats . Он имеет минимальную настройку и дает вам количество наблюдателей на текущей странице + продолжительность цикла дайджеста. Он также может проецировать небольшой график в реальном времени.
незначительное улучшение для такие слова, как ответ.
(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; })();
в AngularJS 1.3.2, a
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; }ссылки
Я взял код прямо из . Конечно, вам, вероятно, нужно обновить селектор элементов приложения (
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'));
Это функции, которые я использую:
/** * @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); }; })();эта функция использует хэш, чтобы не считать одну и ту же область несколько раз.
существует рекурсивная функция, опубликованная в блоге Ларса Эйднеса по адресу http://larseidnes.com/2014/11/05/angularjs-the-bad-parts/ чтобы собрать общее количество наблюдателей. Я сравниваю результат, используя функцию, размещенную здесь, и тот, который он опубликовал в своем блоге, который сгенерировал немного более высокое число. Я не могу сказать какой из них более точный. Просто добавил Здесь в качестве сквозной ссылки.
function getScopes(root) { var scopes = []; function traverse(scope) { scopes.push(scope); if (scope.$$nextSibling) traverse(scope.$$nextSibling); if (scope.$$childHead) traverse(scope.$$childHead); } traverse(root); return scopes; } var rootScope = angular.element(document.querySelectorAll("[ng-app]")).scope(); var scopes = getScopes(rootScope); var watcherLists = scopes.map(function(s) { return s.$$watchers; }); _.uniq(_.flatten(watcherLists)).length;Примечание: возможно, Вам потребуется изменить "ng-app" на "data-ng-app" для вашего углового приложение.
Плантиан ответ быстрее:https://stackoverflow.com/a/18539624/258482
вот функция, которую я написал от руки. Я не думал об использовании рекурсивных функций, но это то, что я сделал вместо этого. Может быть, он и более узкий, я не знаю.
var logScope; //put this somewhere in a global piece of codeзатем поместите это внутри вашего самого высокого контроллера (если вы используете глобальный контроллер ).
$scope.$on('logScope', function () { var target = $scope.$parent, current = target, next; var count = 0; var count1 = 0; var checks = {}; while(count1 < 10000){ //to prevent infinite loops, just in case count1++; if(current.$$watchers) count += current.$$watchers.length; //This if...else is also to prevent infinite loops. //The while loop could be set to true. if(!checks[current.$id]) checks[current.$id] = true; else { console.error('bad', current.$id, current); break; } if(current.$$childHead) current = current.$$childHead; else if(current.$$nextSibling) current = current.$$nextSibling; else if(current.$parent) { while(!current.$$nextSibling && current.$parent) current = current.$parent; if(current.$$nextSibling) current = current.$$nextSibling; else break; } else break; } //sort of by accident, count1 contains the number of scopes. console.log('watchers', count, count1); console.log('globalCtrl', $scope); }); logScope = function () { $scope.$broadcast('logScope'); };и, наконец, в числе:
javascript:logScope();
Comments