In-depth understanding of $apply () and $digest () in angular

Source: Internet
Author: User

reference:http://blog.csdn.net/dm_vincent/article/details/38705099

$apply () and $digest () are two core concepts in AngularJS, but sometimes they are confusing. To understand how AngularJS works, you first need to understand how $apply () and $digest () work. This article is intended to explain what $apply () and $digest () are, and how they are applied in everyday coding.

Explore $apply () and $digest ()

AngularJSProvides a very cool feature called two-way data binding(Two-way Data Binding), this feature greatly simplifies the way our code is written. Data binding means that when theviewscope scopescope model changes, view The data in is also updated to the most recent value. So angularjs{{AModel}}angularjs Behind the scenes you set up a zh-cn watcherscope It is used to update viewwatcherangularjswatcher is the same:

 $scope. $watch ( " amodel  "   // update the DOM with NewValue }); 

The second parameter passed into the $watch () is a callback function that is called when the value of AModel changes. This callback function is not difficult to understand when the AModel is changed, but there is a very important problem! How does AngularJS know when to invoke this callback function? In other words, how does AngularJS know that the AModel has changed before invoking the corresponding callback function? Does it periodically run a function to check if the data in the scope model has changed? Well, that's where the $digest Loop comes in.

In the $digest Loop, thewatchers is triggered. When a watcher is triggered,AngularJS detects the scope model and how it changes so that the callback function associated to the watcher is called. So the next question is, when does the $digest cycle start in various ways?

After calling the$scope. $digest ()After$digestThe cycle begins. Suppose you're in aNg-clickdirective corresponds to theHandlerfunction changes theScopeOne of the data in thisAngularJSis automatically passed through the call to the$digest ()To trigger a round$digestCycle. When$digestOnce the loop is started, it triggers eachwatcherwatchersscopemodelmodelview ({{AModel}) ng-click directives, there are other built-in Instructions and services to let you change models (ng-model, $timeout et ) $ Digest loop.

So far it's good! However, there is a small problem. In the example above,AngularJS does not call $digest () directly, but instead calls the $scope. $apply (), which calls the $rootScope. $digest (). Therefore, a round of $digest cycle starts in the $rootScope and then accesses all the watchers in the children scope .

Now, suppose you associate the Ng-click directive to a button and pass in a function name to Ng-click . When the button is clicked,AngularJS wraps the function into a wrapping function and then passes in to the Scope. $apply (). As a result, your function will be executed normally, modify the models ( if necessary ), and a round $digest Loop will be triggered to ensure that the view will also be updated.

Note: $scope. $apply () automatically calls $rootScope. $digest (). There are two forms of the $apply () method. The first one takes a function as a parameter, executes the function and triggers a round $digest Loop. The second one will not accept any arguments, just trigger a round of $digest loops. We'll see now why the first form is better.

When do I manually invoke the $apply () method?

IfAngularJSAlways put our codeWrapto afunctionIn and incoming$apply ()To start a round$digestLoop, then when do we need to manually call$apply ()Method? As a matter of factAngularJSThere is a very clear requirement that it is only responsible for theAngularJSChanges in the context are automatically responded to(That is, in $apply () changes to modelsangularjs built-in directive is doing so, so any of the The change of span lang= "en-US" >modelviewmodelangularjsangularjs $apply () angularjsmodelsangularjswatchers

For example, if you use setTimeout () in JavaScript to update a scope model, there is no way for AngularJS to know what you have changed. In this case, calling $apply () is your responsibility, by invoking it to trigger a round of $digest loops. Similarly, if you have an instruction to set up a DOM event listener and modify some models in the listener , you also need to manually call $apply () to ensure that changes are correctly reflected in the view .

Let's take a look at an example. Join you have a page, once the page has been loaded, you want to display a message after two seconds. Your implementation might look something like this:

<ng-app= "myApp">    <Ng-controller  = "Messagecontroller">      Delayed message: {{Message}}    </  div>    </body>  
 /*   What happens without an $apply ()  Span style= "COLOR: #008000" >*/  Angular.module ( ' myApp ', []). Controller (' Messagecontroller ', function   ($scope) {$SC Ope.getmessage  = function   () {SetTimeout (  function   () {$scope. Message  = ' F            Etched after 3 seconds ' ;          Console.log ( ' message: ' + $scope. message);        },  2000

By running this example, you will see that after two seconds, the console does show the updated model, however, theview is not updated. Maybe you already know that we forgot to call the $apply () method. Therefore, we need to modify the getMessage ()as follows:

/*What happens with $apply*/Angular.module (' MyApp ', []). Controller (' Messagecontroller ',function($scope) {$scope. GetMessage=function() {setTimeout (function() {$scope. $apply (function() {              //wrapped this within $apply$scope. Message = ' fetched after 3 seconds '; Console.log (' Message: ' +$scope. Message);          }); }, 2000);            } $scope. GetMessage ();  }); 

If you run the example above, you will see that the view is updated after two seconds. The only change is that our code is now wrapped to $scope. $apply () , it automatically triggers $rootScope. $digest (), allowing watchers is triggered to update the view.

Note: By the way, you should use the $timeout service instead of SetTimeout (), because the former will help you call $apply (), So you don't need to call it manually.

Also, note that in the above code you can manually invoke the $apply () without parameters after modifying the model , as follows:

function () {    setTimeout()      {= ' fetched after-seconds ';      Console.log (' message: ' + $scope. message);       // This triggers a $digest    }, a);  };  

The code above uses the second form of the $apply () , which is the form without parameters. Remember that you should always use a $apply () method that accepts a function as a parameter . This is because when you pass a function into the $apply ( ), the function is wrapped in a try... catch block, so that if an exception occurs, the exception is handled $exceptionHandler service .

How many times will the $digest loop run?

When a $digest loop runs,watchers is executed to check if the models in the scope has changed. If there is a change, the corresponding listener function will be executed. This relates to an important issue. What if the listener function itself modifies a scope model ? What will AngularJS do with the situation?

The answer is that the $digest Loop does not run only once. At the end of the current cycle, it will perform a loop again to check if any models have changed . This is the Dirty check (Dirty Checking), which is used to handle the model changes that can be caused when the listener function is executed . As a result, the$digest cycle runs until the model no longer changes, or the number of $digest loops reaches ten times. Therefore, try not to modify the model in the listener function as much as possible .

Note: The $digest Loop will run at least two times, even if the listener function does not change any model. As discussed above, it will run more than once to ensure that the models is unchanged.

Conclusion

I hope this article explains the $apply and $digest clearly . The most important thing to remember is whether AngularJS can detect your modifications to the model. If it cannot be detected, then you need to call $apply () manually.

In-depth understanding of $apply () and $digest () in angular

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.