jusbell
3/14/2014 - 2:33 PM

Count the total number of watches in an application for angular.js

Count the total number of watches in an application for angular.js

(function(targetEl) {
  clear();
  
  var el = null;
  
  if (typeof targetEl == 'string') {
    el = document.querySlector(el);
    if (!el) {
      console.error('Element with CSS selector %s not found', targetEl);
    }
  }
  
  el = angular.element(targetEl || document.body);
  
  if (!el) {
      console.error('Element not found');
  } else if (!el.hasClass('ng-scope')) {
    console.warn('$0 element doesn\'t have a ng-scope, $rootScope will be used.');
  }

  var elScope = angular.element(el).scope();
  var rootScope = elScope.$root;
  
  if (rootScope.$id != '001' && rootScope.$parent !== null) {
    console.error('Not a valid root scope');
    throw new Error('Could not find a valid root scope');
  }

  function removeDups(list) {
    var results = [];
    list.forEach(function(item) {
      if(results.indexOf(item)) {
        results.push(item);
      }
    });
    return results;
  }

  function traverseScope(scope, cb) {
    var visited = {};
    var target, next, current = scope;
    target = current;
    do {
      if (visited[current.$id] || current.$$destroyed) {
        continue;
      }
      cb(current);
      if (!(next = (current.$$childHead ||
          (current !== target && current.$$nextSibling)))) {
        while (current !== target && !(next = current.$$nextSibling)) {
          current = current.$parent;
        }
      }
    } while ((current = next));
  }

  function countTotalWatches(scope) {
    scope = scope || rootScope;
    var totalWatches = 0;
    var totalScopes = 0;
    traverseScope(scope, function(localScope) {
      totalScopes += 1;
      if (localScope.$$watchers && localScope.$$watchers.length > 0) {
        totalWatches += localScope.$$watchers.length;
      }
    });
    return {scopes: totalScopes, watches: totalWatches};
  }

  function countWatchesUnder(el) {
    var scope = angular.element(el).scope();
    return countTotalWatches(scope);
  }

  var totalRoot = countTotalWatches(rootScope);
  console.info('Total number of scopes visited: %d', totalRoot.scopes)
  console.info('Total number of watches: %d', totalRoot.watches);
  
  var totalEl = countWatchesUnder(el);
  console.info('Total number of scopes inside element: %d - %o', totalEl.scopes, el)
  console.info('Total watches inside element: %d - %o', totalEl.watches, el);
})($0);