Home  >  Article  >  Web Front-end  >  AngularJS dirty checking mechanism and the wonderful use of $timeout

AngularJS dirty checking mechanism and the wonderful use of $timeout

陈政宽~
陈政宽~Original
2017-06-28 14:42:581448browse

This article mainly introduces the detailed explanationAngularJSDirty check mechanism and the wonderful use of $timeout. "Dirty check" is one of the core mechanisms in Angular. It is important for realizing two-way binding and MVVM mode. Basics, those who are interested can learn about

||Browser event loop and Angular’s ​​MVW

"Dirty check" is one of the core mechanisms in Angular First, it is an important foundation for realizing two-way binding and MVVM mode.

Angular converts two-way binding into a bunch of watchexpressions, and then recursively checks whether the results of these watch expressions have changed. If so, execute the corresponding watcher function. When the value of the Model no longer changes, no more watcher functions will be triggered, and a complete digest cycle ends.

Because we can quickly develop NodeJS programs using the same language and the same event model without changing our programming thinking, NodeJS quickly became popular, JavaScript full-stack It is also becoming increasingly popular.

We often hear that Angular is an MV* framework. This is because Angular expands the browser's event model and establishes its own context.

||The $watch function in Angular

watch expression is very flexible: it can be a function, it can be a property name on $scope, It can also be an expression in the form of string. The attribute name or expression on $scope will eventually be parsed by the $parse service into a corresponding function to obtain the attribute value.

All watcher functions will be inserted into the head of the scope.$$watchers array by the unshift function for later use by $digest.

Finally, the $watch function will return an unregistered function. Once we call it, we can remove the just registered watcher.

It should be noted that Angular does not use the angular.equals() function for deep comparison by default, because it is faster to use === comparison. Therefore, it compares arrays or Objects. What is being checked is the reference. This results in two expressions with exactly the same content being judged to be different. If in-depth comparison is required, the third optional parameter objectEquality needs to be explicitly set to true, such as $watch('someExp', function(){...}, true).

Angular also provides $watchGroup and $watchCollection methods to monitor arrays or a group of properties.

||$digest function in Angular

As mentioned earlier, Angular expands the browser's event loop. What's going on? ?

When the event forwarded by the event instruction on the View is accepted, the context of Angular will be switched to respond to such events, and the $digest loop will be triggered.

$digest loop actually consists of two while loops. They are: the asynchronous operation queue that handles $evalAsync, and the watchers queue that handles $watch.

When the $digest loop occurs, it will traverse all watchers functions registered on the current $scope and all its child $scopes.

Traversing all watcher functions is called a dirty check. After performing a round of dirty checks, if the value monitored by any watcher has changed, another round of dirty checks will be performed until all watcher functions report that the values ​​they are monitoring have no longer changed.

When the $digest loop ends, the model change results are updated to the DOM. This allows multiple updates to be merged and prevents frequent DOM properties.

It should be noted that before the end of the $digest loop, if more than 10 rounds of dirty checks are exceeded, an exception will be thrown to prevent the dirty checks from looping infinitely.

When will you enter this Angular context and trigger the "dirty check mechanism"? This question is very important, and it is also a troublesome place.

Every event that enters the Angular context environment will execute a $digest loop. For the form interactive control monitored by ngModel, every time a character is entered, a loop is triggered to check the $watcher function so that the View can be updated in time. After Angular1.3, you can use ngModelOptions for configuration to modify the default triggering method.

||$apply

$digest in Angular is an internal function, which should not be directly used in normal application code call it. If you want to actively trigger it, you need to call the scope.$apply function, which is a common public interface that triggers Angular's "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 when we encapsulate the third-party jQuery plug-in, we cannot automatically update the view, but we need to manually call $scope.$apply.

When integrating the jquery plug-in, digest in progress errors sometimes occur. If the bug still cannot be solved after eliminating it, you can consider using $timeout to solve it.

The wonderful use of $timeout

If the variables bound to the interface are modified in the delayed task, then window.setTimeout will not trigger the "dirty check" to update the UI interface. You may think: adding $scope.$apply will solve the problem. Yes, this can solve the problem of UI interface update, but you may encounter another problem:

Error: $digest already in progress

How is this? What's going on? Oh, Angular is doing "dirty checking" internally. A smart programmer cleverly wrote the following piece of code to solve this problem:


function safeApply(scope, fn){ 
  (scope.
phase||scope.$root.
phase) ? fn() : scope.$apply(fn); 
}


In the code, when executing the apply function Previously, we would first check whether Angular was doing "dirty checking" internally. If so, execute the function directly without $apply; otherwise, if dirty checking was not started, $apply would execute the function. Haha, a "perfect" solution, isn't it?

Please note that the author added quotation marks around the word perfect above. Angular has built-in $timeout service for us, which is implemented by Angular wrapping native javascript window.setTimeout.

$timeout has many wonderful uses, but be sure not to abuse it. Implementing the apply function with $timeout should not be our first solution. The first solution should still be to use Angular's built-in instructions.

The above is the entire content of this article. I hope it will be helpful to everyone's study. I also hope that everyone will support Script House.

The above is the detailed content of AngularJS dirty checking mechanism and the wonderful use of $timeout. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn