digest loop walkthrough All Versions
This draft deletes the entire topic.
Examples
-
Implementing two-way-data-binding, to achieve the result from the previous example, could be done with two core functions:
- $digest is called after a user interaction (binding DOM=>variable)
- $watch sets a callback to be called after variable changes (binding variable=>DOM)
note: this is example is a demonstration, not the actual angular code
<input id="input"/> <span id="span"></span>
The two functions we need:
var $watches = []; function $digest(){ $watches.forEach(function($w){ var val = $w.val(); if($w.prevVal !== val){ $w.callback(val, $w.prevVal); $w.prevVal = val; } }) } function $watch(val, callback){ $watches.push({val:val, callback:callback, prevVal: val() }) }
Now we could now use these functions to hook up a variable to the DOM (angular comes with built-in directives which will do this for you):
var realVar; //this is usually done by ng-model directive input1.addEventListener('keyup',function(e){ realVar=e.target.value; $digest() }, true); //this is usually done with {{expressions}} or ng-bind directive $watch(function(){return realVar},function(val){ span1.innerHTML = val; });
Off-course, the real implementations are more complex, and support parameters such as which element to bind to, and what variable to use
A running example could be found here: https://jsfiddle.net/azofxd4j/
-
The previous example is good enough when we need to bind a single html element, to a single variable.
In reality - we need to bind many elements to many variables:
<span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>
This
ng-repeat
binds 5 elements to 5 variables callednumber
, with a different value for each of them!
The way angular achieves this behavior is using a separate context for each element which needs separate variables. This context is called a scope.
Each scope contains properties, which are the variables bound to the DOM, and the
$digest
and$watch
functions are implemented as methods of the scope.The DOM is a tree, and variables need to be used in different levels of the tree:
<div> <input ng-model="person.name" /> <span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span> </div>
But as we saw, the context(or scope) of variables inside
ng-repeat
is different to the context above it. To solve this - angular implements scopes as a tree.Each scope has an array of children, and calling its
$digest
method will run all of its children's$digest
method.This way - after changing the input -
$digest
is called for the div's scope, which then runs the$digest
for its 5 children - which will update its content.
A simple implementation for a scope, could look like this:
function $scope(){ this.$children = []; this.$watches = []; } $scope.prototype.$digest = function(){ this.$watches.forEach(function($w){ var val = $w.val(); if($w.prevVal !== val){ $w.callback(val, $w.prevVal); $w.prevVal = val; } }); this.$children.forEach(function(c){ c.$digest(); }); } $scope.prototype.$watch = function(val, callback){ this.$watches.push({val:val, callback:callback, prevVal: val() }) }
note: this is example is a demonstration, not the actual angular code
-
-
Angular has some magic under its hood. it enables binding DOM to real js variables.
Angular uses a loop, named the "digest loop", which is called after any change of a variable - calling callbacks which update the DOM.
For example, the
ng-model
directive attaches akeyup
eventListener to this input:<input ng-model="variable" />
Every time the
keyup
event fires, the digest loop starts.At some point, the digest loop iterates over a callback which updates the contents of this span:
<span>{{variable}}</span>
The basic life-cycle of this example, summarizes (very Schematically) how angular works::
- Angular scans html
ng-model
directive creates akeyup
listener on inputexpression
inside span adds a callback to digest cycle
- User interacts with input
keyup
listener starts digest cycle- digest cycle calles the callback
- Callback updates span's contents
- Angular scans html
Syntax
- $scope.$watch(watchExpression, callback, [deep compare])
- $scope.$digest()
- $scope.$apply([exp])
Sign up or log in
Save edit as a guest
Join Stack Overflow
Using Google
Using Facebook
Using Email and Password
We recognize you from another Stack Exchange Network site!
Join and Save Draft