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

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

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.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.


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

Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


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

{{ parent.tldr }}

{{ parent.urlSource.name }}