Explanation of AngularJS dirty check mechanism and the usage of $ timeout, angularjstimeout
| Browser event loop and Angular MVW
"Dirty checking" is one of the core mechanisms in Angular. It is an important basis for implementing bidirectional binding and MVVM mode.
Angular converts two-way binding to a bunch of watch expressions, and recursively checks whether the results of these watch expressions have changed. If they have changed, execute the corresponding watcher function. When the value of the Model does not change, the watcher function will no longer be triggered, and a complete digest loop will end.
Because we can quickly develop NodeJS programs using the same language and event model without changing programming thinking, NodeJS is becoming increasingly popular with JavaScript full-stack.
We often hear that Angular is a MV * framework, because Angular expands the browser's event model and builds its own context environment.
| $ Watch function in Angular
Watch expressions are flexible: they can be a function, an attribute name on $ scope, or a string expression. The attribute name or expression on $ scope will eventually be parsed by the $ parse service as a function for retrieving attribute values in the response.
All watcher functions are inserted into the scope. $ watchers array header by the unshift function for later $ digest usage.
Finally, the $ watch function returns an anti-register function. Once we call it, we can remove the registered watcher.
Angular does not use angular by default. the equals () function performs In-depth comparison because the = method is faster, so it checks references when comparing arrays or objects. This results in two expressions with identical content being determined to be different. If deep comparison is required, the third optional parameter objectEquality needs to be explicitly set to true, for example, $ watch ('someexp', function () {...}, true ).
Angular also provides the $ watchGroup and $ watchCollection methods to listen to arrays or a set of attributes.
| $ Digest function in Angular
As mentioned above, Angular expands the browser's event loop. How is this happening?
When you receive the event forwarded by the event command on the View, it will switch to the Angular Context Environment to respond to such events, and the $ digest loop will be triggered.
$ Digest contains two while loops. They are: processing the Asynchronous Operation queue of $ evalAsync, processing the watchers queue of $ watch.
When a $ digest loop occurs, it traverses all the watchers functions registered on the current $ scope and all its sub-$ scope.
Traversing all watcher functions is called a round of dirty checking. After a round of dirty checking is executed, if any value monitored by watcher has changed, a round of dirty checking will be performed again, until all watcher functions report that the value they listen for is no longer changed.
When the $ digest loop ends, the model change result is updated to the DOM. In this way, multiple updates can be merged to prevent frequent DOM attributes.
Note that if more than 10 rounds of dirty checks are performed before the $ digest loop ends, an exception is thrown to prevent the dirty checks from going through infinite loops.
When will this Angular context trigger the "dirty checking mechanism? This problem is very important, and it is also a headache.
Every event that enters the Angular Context Environment executes a $ digest loop. For the form interaction control monitored by ngModel, each input of a character triggers a loop to check the $ watcher function, so that the View can be updated in time. You can use ngModelOptions after Angular1.3 to modify the default trigger mode.
| $ Apply in Angular
$ Digest is an internal function and should not be called directly in normal application code. To actively trigger it, call the scope. $ apply function, which is a common public interface that triggers Angular "Dirty checking mechanism.
It should be noted that Angular can only manage the behavior triggering methods it knows, but cannot cover all Angular operation scenarios. This is why we cannot update the view automatically when encapsulating a third-party jQuery plug-in. Instead, we need to manually call $ scope. $ apply.
When the jquery plug-in is integrated, sometimes the digest in progress error occurs. If the Bug cannot be solved after it is eliminated, you can use $ timeout to solve the problem.
$ Timeout
Modify the variable bound to the interface in the delayed task, so window. setTimeout does not trigger a "dirty check" to update the UI. You may think: simply add $ scope. $ apply. Yes, this can solve the problem of UI update, but you may encounter another problem:
Error: $ digest already in progress
What's the problem? Oh, Angular is performing a "dirty check" internally ". A clever programmer cleverly writes the following code to solve this problem:
function safeApply(scope, fn){ (scope.phase||scope.$root.phase) ? fn() : scope.$apply(fn); }
In the code, before executing the apply function, check whether Angular is performing a "dirty check". If so, execute the function directly without $ apply. Otherwise, the dirty check is not started, then $ apply executes the function. Oh, it's a perfect solution, isn't it?
Please note that I have placed quotation marks on the perfect word above. Angular has built the $ timeout service for us. It is implemented by Angular packaging native javascript window. setTimeout.
$ Timeout has many advantages, but it must not be abused. $ timeout implementation of the apply function should not be our first solution. The first solution should still be to use Angular built-in commands.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.