Friday, July 29, 2016

AngularJS $watch() , $digest() and $apply()

AngularJS $watch() , $digest() and $apply()

When you create a data binding in your view to a variable on the $scope object, AngularJS creates a "watch" internally. A watch means that AngularJS watches changes in the variable on the $scope object. These watches are created using the $scope.$watch() function.

When you register a watch you pass two functions as parameters to the $watch() function:
* A value function
* A listener function

Example :

$scope.$watch(function() {}, function() {} );
The value function should return the value which is being watched. AngularJS can then check the value returned(current value) against the last calculated value. That way AngularJS can determine if the value has changed. If yes, then the corresponding listener function executes.

Example 1:

$scope.$watch(function(scope) { return }, function() {} );

Example 2:

$scope.$watch(function(scope) { return }, function(newValue, oldValue) { document.getElementById("").innerHTML = "" + newValue + ""; } );


The $digest cycle starts as a result of a call to $scope.$digest(). Assume that you are changing a scope model in the ng-click event, in that case AngularJS automatically triggers a $digest cycle by calling $digest(). (In addition to ng-click, there are several other built-in directives/services that let you change models (e.g. ng-model, $timeout, etc) and automatically trigger a $digest cycle.) This $digest() function iterates through all watches and checks if any of the watched variables have changed. If a watched variable has changed, a corresponding listener function is called. The listener function does whatever work it needs to do, for instance changing an HTML text to reflect the new value of the watched variable. Thus, the $digest() function is what triggers the data binding to update.


The $scope.$apply() function takes a function as parameter which is executed, and after that $scope.$digest() is called internally. That makes it easier for you to make sure that all watches are checked, and thus all data bindings refreshed. Here is an $apply() example:
$scope.$apply(function() { $ = "Another value"; });
$apply() is called only for those model changes which are done inside AngularJS’ context. Angular’s built-in directives already do this so that any model changes you make are reflected in the view. However, if you change any model outside of the Angular context, then you need to inform Angular of the changes by calling $apply() manually. It’s like telling Angular that you are changing some models and it should fire the watchers so that your changes propagate properly. For example, if you use JavaScript’s setTimeout() function to update a scope model, Angular has no way of knowing what you might change. In this case it’s your responsibility to call $apply() manually, which triggers a $digest cycle. At a minimum, $digest will run twice even if your listener functions don’t change any models. The $digest cycle keeps looping until there are no more model changes, or it hits the max loop count of 10
$apply invokes $digest on rootScope and it means that it reevaluate all watchers in all available scope and this may cause a performance hit for large scope hierarchy.
$digest() is used to re-evaluate specific scope and its children.

No comments:

Post a Comment