How often does the AngularJS digest loop run?

后端 未结 3 1772
无人及你
无人及你 2021-02-02 08:03

When discussing the merits of AngularJS, two-way data binding is often touted as a major benefit of Angular over other JS frameworks. Digging deeper, the documentation suggests

3条回答
  •  执念已碎
    2021-02-02 08:24

    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

    1. DOM events
    2. XHR responses firing callbacks
    3. Browser's location changes
    4. Timers (setTimout, setInterval) firing the callbacks

    Correspondingly, Angular trigger digest loop at, for instance

    1. input directives+ngModel, ngClick, ngMouseOver etc.
    2. $http and $resource
    3. $location
    4. $timeout

    Try to answer those bonus questions from my understanding:

    1. 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.
    2. 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.
    3. 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

    1. Watch callback should be coded as simpler/efficient as possible, for example detach complicated algorithm code to, for example, worker threads
    2. Proactively remove a watch if it is not used anymore
    3. 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.

提交回复
热议问题