Skip to content

Instantly share code, notes, and snippets.

@shuhblam
Last active August 13, 2017 19:18
Show Gist options
  • Save shuhblam/8f2836a471b714902efb040767414a1c to your computer and use it in GitHub Desktop.
Save shuhblam/8f2836a471b714902efb040767414a1c to your computer and use it in GitHub Desktop.

Monitoring angular $$watchers

There are a few chrome extensions that will tell you the total count of your angular $$watchers but in order to narrow down the problem areas I needed more insight into which elements were causing problems. This script helped me by giving me the ability to:

  • Quickly identify the top x elements with the highest number of $$watchers
  • Get the total $$watchers for any element including all of it's descendants
  • Get all $$watchers for the current documentElement

For debugging I recommend using chrome snippets. Paste the watcher.js script into a new snippet, save it and then run it. Once you load the snippet you can call any functions it loaded directly from the console as many times as you want.

Examples

// Get an array of all watchers for the current document
getWatchers()

// Get an array of all watchers for an element and it's descendants
getWatchers(element)

// Log the most expensive elements to the console sorted by watcher count
// It is not required but I recommend passing an integer to limit
// the number of elements logged. By default will log all elements with
// watchers. This can be hundreds of lines logged without a limit.
logWatchers(10);
var elementsWithWatchers = [];
function getWatchers(root) {
root = angular.element(root || document.documentElement);
var watcherCount = 0;
function getElemWatchers(element) {
var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
var scopeWatchers = getWatchersFromScope(element.data().$scope);
var watchers = scopeWatchers.concat(isolateWatchers);
if(watchers.length) {
elementsWithWatchers.push({
count: watchers.length,
element: element
});
}
angular.forEach(element.children(), function (childElement) {
watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
});
return watchers;
}
function getWatchersFromScope(scope) {
if (scope) {
return scope.$$watchers || [];
} else {
return [];
}
}
return getElemWatchers(root);
}
function logWatchers(numberOfItemsToLog) {
elementsWithWatchers = [];
getWatchers();
elementsWithWatchers.sort(function(a,b){
return b.count - a.count;
});
if(numberOfItemsToLog){
elementsWithWatchers = elementsWithWatchers.slice(0, numberOfItemsToLog - 1);
}
elementsWithWatchers.forEach(function(watcher, i) {
console.log(watcher.count, watcher.element[0]);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment