Aby zrozumieć $digest i $apply oraz różnicę pomiędzy nimi, przyjrzyjmy się najpierw, czym jest cykl $digest.
Cykl $digest można rozumieć jako pętlę, w której podczas interacji AngularJS sprawdza, czy nastąpiły jakieś zmiany w nasłuchiwanych zmiennych (we wszystkich nasłuchiwanych zmiennych we wszystkich scope’ach). Na przykład, jeśli została w kontrolerze zdefiniowana zmienna $scope.val
i zmienna ta została oznaczona jako zmienna nasłuchiwana (obserwowana), wtedy domyślnie będzie ona sprawdzana przy każdej interacji.
Czy wszystkie zmiene w $scope’ach są domyślnie nasłuchiwane?
Nie, ponieważ byłoby to zbyt dużym obciążeniem. Nasłuchiwane są tylko te zmienne, które są interpolowane (implicit watcher) lub mają ręcznie utworzoną funkcję nasłuchującą $watcher (explicit watcher).
Zarówno $digest jak i $apply służą do ręcznego zaktualizowania wartości powiązanych ze $scope. Różnica jest taka, że $digest aktualizuje $scope lokalny oraz swoich potomków, a $apply aktualizuje wszystkie $scope’s.
angular .module('myApp', []) .controller('defaultCtrl', ['$scope', function($scope) { $scope.number = 1; // explicit watcher $scope.$watch('number', function(newval, oldval) { console.log('Liczba: ', $scope.number, newval, oldval); }) $scope.add = function() { $scope.number++; } $scope.dec = function() { $scope.number--; } }]) .controller('outerCtrl', function($scope) {}) .controller('firstInnerCtrl', function($scope) { $scope.go = function() { setTimeout(function() { $scope.msg = 'upłynął czas'; console.log('message firstInnerCtrl:' + $scope.msg); }, 1000); } $scope.go(); }) .controller('secondInnerCtrl', function($scope) { $scope.go = function() { setTimeout(function() { $scope.msg = 'upłynął czas'; console.log('message firstInnerCtrl:' + $scope.msg); $scope.$digest(); // $scope.$apply(); }, 2000); } $scope.go(); });