Short direct answer to the main question is "NO", angular doesn't automatically trigger digest loop.
TL;DR answer:
Digest loop is designed to run dirty check over POJO models associated with Angular scope instances, so it only needs to run when a model might be changed. In a single page Web application running inside Browser, the following actions/events could lead to a model change
- DOM events
- XHR responses firing callbacks
- Browser's location changes
- Timers (setTimout, setInterval) firing the callbacks
Correspondingly, Angular trigger digest loop at, for instance
- input directives+ngModel, ngClick, ngMouseOver etc.
- $http and $resource
- $location
- $timeout
Try to answer those bonus questions from my understanding:
- ngModel directive often used with angular input directives (text, select etc) together, and the laters will listen on "change" events and call $setViewValue API exposed from ngModelController in order to sync back dom value. During the sync process, ngModelController will make sure to trigger digest loop.
- digest loop is different from JS event loop, the later is concept of JS runtime (checkout the great visualised session https://www.youtube.com/watch?v=8aGhZQkoFbQ) which run against event queue and remove consumed event from the queue automatically, but digest loop never remove watch from its watch list unless you explicitly unwatch.
- the number of digest loops per second depends on the efficiency of all watch callbacks being executed through the loop . If some bad code took one second to finish, then this digest loop would cost more than 1 sec.
So some key practices for avoid angular performance pitfalls are
- Watch callback should be coded as simpler/efficient as possible, for example detach complicated algorithm code to, for example, worker threads
- Proactively remove a watch if it is not used anymore
- Prefer to call $scope.$digest() instead of $scope.$apply() if applicable, $digest() only run part of scope tree and ensure the models associated under the subtree is reflecting to view. But $apply() will run against entire scope tree, it will iterate through more watches.