Как подсчитать общее количество часов на странице?

Есть ли способ, в JavaScript, подсчитать количество угловых часов на всей странице?

Мы используем Batarang , но это не всегда соответствует нашим потребностям. Наше приложение большое, и мы заинтересованы в использовании автоматических тестов, чтобы проверить, увеличивается ли количество часов.

Было бы также полезно считать часы на основе controllerа.

Изменить : вот моя попытка. Он учитывает часы во всем с classом 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; })(); 

(Вам может потребоваться изменить 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' может потребоваться изменить.


оригинал

Я сделал то же самое, кроме того, что я проверил атрибут data элемента HTML, а не его class. Я побежал сюда:

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'); } } } 

И ничего не напечатано, поэтому я предполагаю, что мое лучше (тем, что он нашел больше часов), - но мне не хватает интимных угловых знаний, чтобы точно знать, что моя не является надлежащим подмножеством набора решений.

Я думаю, что упомянутые подходы являются неточными, так как они подсчитывают наблюдателей в одном и том же диапазоне. Вот моя версия букмарклета:

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-statshttps://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 к countWatchers добавлен метод countWatchers:

 / **
  * Метод @ngdoc
  * @name $ rootScope.Scope # $ countWatchers
  * @module ngMock
  * @описание
  * Подсчитывает всех наблюдателей прямых и косвенных дочерних областей текущего объема.
  *
  * Наблюдатели текущего объема включены в подсчет, и поэтому все наблюдатели
  * изолировать области ребенка.
  *
  * @returns {number} Общее количество наблюдателей.
  * /

  функция countWatchers () 
    {
    var root = angular.element (document) .injector (). get ('$ rootScope');
    var count = root. $$ watchers?  root $$ watchers.length: 0;  // включить текущую область действия
    var pendingChildHeads = [root. $$ childHead];
    var currentScope;

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

     while (currentScope) 
       {
       count + = currentScope. $$ наблюдатели?  currentScope. $$ watchers.length: 0;
       pendingChildHeads.push (currentScope $$ childHead.);
       currentScope = currentScope. $$ nextSibling;
       }
     }

    счетчик возврата;
    }

Рекомендации

  • Список изменений в AngularJS: 1.3.2

  • ngMock: $ rootScope.Scope. $ countWatchers

Я взял код ниже непосредственно из функции $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')); 

Это функции, которые я использую:

 /** * @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); }; })(); 

Эта функция использует hash, чтобы не считать одну и ту же область несколько раз.

Существует рекурсивная функция, опубликованная блогом Ларса Эйдна по адресу 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 

Затем поместите это в свой самый высокий controller (если вы используете глобальный controller).

 $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(); 
  • Как получить предыдущий элемент в ng-repeat?
  • если путь ngSrc разрешается до 404, существует ли способ отступить к умолчанию?
  • Сохранять разрывы строк в angularjs
  • Угловая JS: Какова потребность в функции ссылки директивы, когда у нас уже есть controller директивы с объемом?
  • Автоматическое выключение с помощью Angularjs на основе пользователя бездействия
  • Смутно о Сервисе и Фабрике
  • Как сгенерировать URL-ссылки с привязкой к url ​​с помощью AngularJS?
  • как вводить зависимость в module.config (configFn) в угловом
  • Каковы различия между ng-repeat и ng-options и почему они не ведут себя одинаково?
  • AngularJS - как переопределить директиву ngClick
  • угловой $ q, Как связать несколько обещаний внутри и после цикла
  • Interesting Posts

    Обновления Windows и поиск драйверов потребляют огромное количество оперативной памяти.

    Методология интерфейсов Java: должен ли каждый class реализовывать интерфейс?

    Как обрабатывать код, когда приложение убито путем прокрутки в Android?

    Передача данных между формами WPF

    Зачем нужна ошибка? Идентификатор проекта, используемый для вызова API разработчика Google Play, не был связан в консоли разработчика Google Play. ‘

    Почему мой SSD внутренне шифрует данные, даже без набора пароля?

    Преобразование числового представления столбца «переменная» в исходную строку после таяния с использованием шаблонов

    Почему мой журнал в пространстве имен std?

    Как сбросить время на моем компьютере, не включив его?

    Скрыть «Вход в систему», «# программы» на WinXP Fast User Switching

    Когда адаптер виртуальной машины VirtualBox установлен на NAT, VM может получить доступ к хост-компьютеру?

    Преобразование PDF в многостраничный tiff (группа 4)

    Java выполняет команду с пробелом в пути

    Android MapView – автоматическое масштабирование до тех пор, пока не будут видны все ItemizedOverlay

    ggplot2 двухстрочная метка с выражением

    Давайте будем гением компьютера.