Speed up your AngularJS app by limiting $digest cycles

We all know the speed of our app is very important and in the early stages of development there are rarely any issues with speed, but as the app grows and as we move into testing with real data we can see it getting slow unless we take speed into account throughout development.

When the user interacts with the UI, such as tying in an input box, Angular will run the $digest loop to see if anything has changed. The faster the cycle, the faster the two-way data binding and the better the user experience.

If the $digest loop is very large then the user is going to see lag in the UI and this is definitely something we want to avoid.

One option is to cut down on the number of $digest loops by using ngModelOptions.

ngModelOptions can be declared at the module level so you don’t need to declare it at the individual input field level for every element in your app.

<body ng-app="myApp" ng-model-options="{ updateOn: 'keyup change click blur', debounce: { keyup: 500, click: 0, change: 0, blur: 0 } }">

Doing the above would have all the input fields in myApp module inherit the ng-model-options. These can then be overridden in specific input fields if required

You could just use updateOn: ‘default blur’ however the problem with this is that radios and check boxes stop working as expected. By using updateOn: ‘keyup change click blur’ we have found all form elements work as expected (in all browsers we dev for) but it significantly cuts down the number of digest cycles.

As you’re developing you may like to keep track of the number of $digest cycles to ensure your optimising for speed. The below directive will display the count.

'use strict';
/** 
  * 
*/
app.directive('trackDigests', ["$rootScope", function($rootScope) {
  return {
    restrict: 'EA',
    link: function link($scope, $element, $attrs) {
      var count = 0;
      function countDigests() {
        count++;
        $element[0].innerHTML = '$digests: '+count;
      }
      $rootScope.$watch(countDigests);
    }
  };
}]);

You add the below into your UI where you want to see the count.

<track-digests></track-digests>

Another good practice is implementing one-way binding for any data that doesn’t require two-way binding. Just add :: in your templates where required.

<p>Hello {{::name}}!</p>

 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top