Digest Cycle w dużym skrócie jest to sposób w jaki AngularJS automatycznie aktualizuje wartości. A trochę dokładniej to…
Watch list
Aby móc rozmawiać o Digest Cycle najpierw trzeba zrozumieć czym jest Watch list. A nie jest to niczym szczególnym – jest to zwyczajna lista zawierająca obserwowane zmienne/obiekty (tzw. „watchery”).
Jak zmienne/obiekty trafiają do Watch list?
1. Poprzez automatyczne wykrycie
Przykładowo dla takiego szablonu i kontrolera:
<div ng-controller="mainController">{{welcomeMessage}}</div>
app.controller('mainController', ['$scope', ($scope) {
$scope.welcomeMessage= 'Witaj';
}]);
zmienna welcomeMessage zostanie automatycznie dodana do obserwowanych (po to żeby widok miał cały czas aktualną wartość, potrzebne jest obserwowanie zmian).
2. Poprzez dyrektywę ng-model
<input type="text" name="userName" ng-model="userName">
3. Poprzez dodanie „watchera” ręcznie
Przykładowy kod (tutaj szerszy opis):
scope.$watch('someVariable', function(newValue, oldValue) {
//do what you need
});
* Każdy scope ma swoją watch listę
Warto także wiedzieć, że każdy scope (wraz z Root Scopem) posiada oddzielną watch listę.
Digest cycle
Jest to sytuacja, w której mechanizm AngularJS przechodzi przez wszystkie elementy watch listy i sprawdza czy coś się zmieniło (dirty checking):

Jeśli natrafi na jakąś zmianę to odpala powiązaną funkcję z watcherem (o ile takowa została zdefiniowana) a następnie odpala następny przebieg (ponieważ funkcje, jak i wyrażenia, mogą wpływać na inne zmienne, które są na watch listach). Jeśli konkretny przebieg nie wykryje już mian, to dopiero wtedy zmiany są propagowane do DOM.
Ograniczenie przebiegów
Domyślnie AngularJS robi maksymalnie 10 przebiegów. Jeśli jest przekroczona ta liczba to z dużym prawdopodobieństwem można stwierdzić, że mamy tak zwany cykl (watcher A zmienia dane, które obserwuje watcher B a watcher B zmienia dane które obserwuje watcher A).
Digest jest wykonywany zawsze przynajmniej jeden raz, a maksymalnie dziesięć. Wykonywane są ponowne okrążenia dlatego, że działanie funkcji powiązanych z watcherami mogło zmienić coś w innych watcherach.
Co powoduje wywołanie Digest Cycle?
1. Zmiana wartości, która jest na którejś z Watch list
2. Jawne wywołanie funkcji $digest lub $apply
Dla ciekawskich – jak to jest zaimplementowane?
A no AngularJS przy kompilacji dyrektyw nakłada najzwyklejsze event listenery (patrz -> element.addEventListener(type, handle);):
removeData: jqLiteRemoveData,
on: function jqLiteOn(element, type, fn, unsupported) {
//I've removed some code
var addHandler = function(type, specialHandlerWrapper, noEventListener) {
var eventFns = events[type];
if (!eventFns) {
eventFns = events[type] = [];
eventFns.specialHandlerWrapper = specialHandlerWrapper;
if (type !== '$destroy' && !noEventListener) {
element.addEventListener(type, handle);
}
}
eventFns.push(fn);
};
Powyższy kod jest wywoływany przy tworzeniu dyrektyw (patrz -> element.on…):
function createEventDirective($parse, $rootScope, $exceptionHandler, directiveName, eventName, forceAsync) {
return {
restrict: 'A',
compile: function($element, attr) {
var fn = $parse(attr[directiveName]);
return function ngEventHandler(scope, element) {
element.on(eventName, function(event) {
Warto zajrzeć
Kod źródłowy AngularJS https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.js