Counting the number of watchers on a page in angular.js
A large number of angular.js watchers are usually the source of slowdowns in angular build applications. When using
{{foo}}
or $scope.$watch(...)
angular will create a new watcher to check for changes on each $digest
cycle and be
able to notify the controller or update the view. It is generally accepted that once the number of watchers reaches
2000+, an application will start to suffer.
With the following, you can count the number of watchers on a page.
(function (window) { var slice = [].slice; window.ngWatchCount = function (base) { var elems; if (base && typeof base !== 'string') { elems = slice.call(base.querySelectorAll('*')); elems.unshift(base); } else if (typeof base === 'string') { elems = slice.call(document.querySelectorAll(base + ', ' + base + ' *')); } else { elems = slice.call(document.querySelectorAll('*')); } return elems .map(function (elem) { var data = angular.element(elem).data(); //if (data.$scope && data.$scope.$$watchers && data.$scope.$$watchers.length) { // elem.setAttribute("angular-watch-count", data.$scope.$$watchers.length); //} return data.$scope || null; }) .filter(function (scope) { return scope && scope.$$watchers; }) .reduce( function (tmp, scope) { if (tmp.cache[scope.$id]) { return tmp; } tmp.cache[scope.$id] = true; tmp.count += scope.$$watchers.length; return tmp; }, { count: 0, cache: {}, }, ).count; }; })(window); // usage // ngWatchCount(document.getElementById("foo")) => 200 (passing a dom element) // ngWatchCount(".some-qsa-query") => 900 (passing a querySelectorAll selector string, selector included) // ngWatchCount() == ngWatchCount(document) => 1400 (no argument, will find all watches)
Just paste it in the console or put it in some debug block on the page.