Over a million developers have joined DZone.

AngularJS Quick Tip: Counting Watches

DZone's Guide to

AngularJS Quick Tip: Counting Watches

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

Sometimes, for troubleshooting purposes, it is important to understand how many watches exist in an Angular app. You may be surprised to find that in certain scenarios, you are generating many more watches than you anticipate. For example, simply using ng-repeat on a long list will create a watch for every element unless you use a library like bindonce. Fortunately, because Angular is tightly coupled to the HTML DOM, it is not difficult to hook in and look under the hood.

To make it even easier, I created a simple module called jlikness.watch that contains a single directive and service. To use the module, you simply place a directive at the topmost element in your app you want to count watches from, then reference the service and call the countWatches() method any time you wish to get an updated count.

The main logic simply checks to see if an element has an associated scope, and if it does, uses Angular’s internal $$watchers collection to add the count.

if (element.scope()) {
  _this.watchCount += element.scope().$watchers.length;

The function then recursively calls itself for each child of the element being inspected.

angular.forEach(element.children(), function (child) {

This naive implementation will give a count, but because scope() walks up the DOM hierarchy to find the first parent with a valid scope the count may be off. The code can duplicate counts because children of the element may point to the same parent scope. The fix is to track the scopes by their Angular $id. You can see that code implemented in the latest source at the jlikness.watch repository.

The directive is used to pass the root element to the service as a starting point for the recursive count.

w.directive('jlWatch', ['jlWatchService', function (ws) {
  return {
  restrict: 'A',
  link: function (scope, elem) {

Using the directive and service is very straightforward, as shown in this example. Click the refresh button to see the number of watches generated for even a fairly small app.

(function (app) {
  app.run(['$rootScope', 'jlWatchService', function ($rootScope, ws) {
  angular.extend($rootScope, {
  title: 'Angular Watchers',
  watchCount: 0,
  refreshWatches: function () {
  this.watchCount = ws.countWatches();
})(angular.module('myApp', ['jlikness.watch'])); 

That’s it – plain and simple, but very eye-opening when you start dealing with complex pages and long lists.

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat


Published at DZone with permission of Jeremy Likness, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}