$apply and $digest

To understand $digest, we must first understand $apply().

$apply()

Is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). If you look through the AngularJS source code, you can see where the framework implicitly calls $apply for the Angular equivalents of these events

index.html :

<!DOCTYPE html>
<html ng-app='app'>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    {{rootMessage}}
    <div ng-controller="HomeCtrl">
      {{childMessage}}
    </div>
  </body>
</html>

app.js :

var app = angular.module('app', [])
  .controller('HomeCtrl', ['$scope','$rootScope', function($scope, $rootScope){
    $rootScope.rootMessage = "Initial Root Message";    
    $scope.childMessage = "Initial Child Message";


    setTimeout(function(){
      console.log('timeout expired...');

      $rootScope.rootMessage = "New Root Message";    
      $scope.childMessage = "New Child Message";

      /*$scope.$apply();*/
      // On time expired change both message.
      // This made the change from the rootscope.

      /*$scope.$digest();*/
      // On time expired only change child message.
      // This only made the change on the loop.
    }, 2000)


  }]);

$digest()

The digest loop is responsible to update DOM elements with the changes made to the model as well as executing any registered watcher functions.

The $digest loop is fired when the browser receives an event that can be managed by the angular context. This loop is made up of two smaller loops. One processes the $evalAsync queue and the other one processes the $watch list.

The $digest loop keeps iterating until the $evalAsync queue is empty and the $watch list does not detect any changes in the model. The $evalAsync queue contains those tasks which are scheduled by $evalAsync() function from a directive or controller.

The $watch list contains watches correspondence to each DOM element which is bound to the $scope object. These watches are resolved in the $digest loop through a process called dirty checking. The dirty checking is a process which checks whether a value has changed, if the value has changed, it set the $scope as dirty. If the $scope is dirty, another $digest loop is triggered.

When you do the changes to the scope outside the angular context, you have to call $apply() function explicitly on the scope to trigger $digest cycle immediately.