Roadmap › AngularJS (1.x) — Legacy › Module: Scope, Digest and Directives
Lessons in this course (13)

9. The digest cycle, $watch and $apply

Advanced★ Must knowLesson 9 of 13
  • Each binding ({{ }}, ng-model, $watch) registers a watcher.
  • $digest() loops over all watchers on a scope and its children, comparing current vs last values (dirty checking); if anything changed, it runs listeners and loops again until stable (max 10 → 10 $digest() iterations reached error).
  • $apply(fn) runs fn then $rootScope.$digest() — needed when changing the model outside AngularJS (jQuery events, setTimeout, third-party callbacks).
  • $watch(expr, listener) — reference/value check; $watchCollection — shallow array/object; $watch(expr, fn, true) — deep (expensive).
  • $scope.$on/$emit/$broadcast — events up ($emit) or down ($broadcast) the scope tree.
js
$scope.$watch(() => vm.filter, (newVal, oldVal) => { if (newVal !== oldVal) vm.reload(); });
someJQueryWidget.on("change", value => $scope.$apply(() => (vm.value = value)));
const off = $rootScope.$on("cart:updated", handler);
$scope.$on("$destroy", off);                         // always unregister

Rule of thumb: keep watchers under ~2,000 per page for smooth performance.