Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

AngularJS Quick Tip: Counting Watches

DZone's Guide to

AngularJS Quick Tip: Counting Watches

· Java Zone ·
Free Resource

Learn how to build stream processing applications in Java-includes reference application. Brought to you in partnership with Hazelcast.

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) {
  iterate(angular.element(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) {
  ws.register(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.

Learn how to build distributed stream processing applications in Java that elastically scale to meet demand- includes reference application.  Brought to you in partnership with Hazelcast.

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}