when $digest cycle is called?
Asked Answered
N

3

22

I'm very confused when a digest cycle is happening, is it called periodically based on a timer every 50ms (as it says here and implied here) or is it called after every event that enters the angular context (as it says here, here and here) ?

Example when it is matter:

In my model, I have a variable called myVar with the value of 3. In my HTML, I have {{myvar}}. An event such as a button click is fired and raises a handler in the controller, the code inside the handler is:

$scope.myVar = 4;
// some heavy actions takes place for 3 seconds...
$scope.myVar = 5;

Assuming the UI thread is not blocked, what will the user see after the button click? will he see only 5 or will he see 4 and after 3 seconds 5?

Nitrile answered 4/5, 2014 at 18:33 Comment(8)
The digest cycle happens periodically. You can prove this to yourself by using Chrome and making a profile recording. View it with the flame chart and you will see the digest cycles happening.Epirogeny
@Epirogeny then why is it also called after some events? it is unnecessaryNitrile
You are asking why so many people feel the need to manually trigger digest cycles and use things like $scope.$apply()? In a lot of cases they probably do not need to and it is a symptom of a larger/different problem. It is necessary sometimes to do so, when things "outside" of angular have changed.Epirogeny
@Epirogeny my question is: 1) if it is called periodically why outside of angular it is necessary? it will be evaluated anyway. 2) why $apply is called automatically after a lot of events such as ng-click? see hereNitrile
Ah, ok, the answer is that the scope is not marked as dirty by things that happen "outside" of angular - and so it is not checked in the next digest cycle. ng-click/$scope.$apply() will mark that scope as dirty, and then that scope and its stuff will get checked.Epirogeny
@Epirogeny sorry for my ignorance but I read that $apply is actually calling $rootScope.$digest so how is it marking the scope as dirty and why calling $rootScope.$digest if it is already running periodically?Nitrile
let us continue this discussion in chatNitrile
I'd recommend to read the following article for better understanding the digest cycle in AngularJS: sitepoint.com/understanding-angulars-apply-digestPuritanical
O
28

I think the description of the digest cycle at http://blog.bguiz.com/post/60397801810/digest-cycles-in-single-page-apps that it is

code that runs at an interval

is very misleading, and to be honest, when referring to Angular, I would even say wrong. To quote Pawel Kozlowski, Mastering Web Application Development with AngularJS

AngularJS does not use any kind of polling mechanism to periodically check for model changes

To prove there is no polling, if you have a template of

<p>{{state}}</p>

and controller code of

$scope.state = 'Initial';
// Deliberately *not* using $timeout here
$window.setTimeout(function() {
  $scope.state = 'Changed';
},1000);

as in this plunker, then the string shown to the user will remain as Initial and never change to Changed.

If you're wondering why you often see calls to $apply, but not always, it is probably because the various directives that come with Angular, such as ngClick or ngChange will call $apply themselves, which will then trigger the cycle. Event listeners to native JS events directly will not do this, so they will have to deliberately call $apply to have any changes made reflected in templates.

Offstage answered 4/5, 2014 at 19:17 Comment(0)
I
13

The digest process is kicked-in when any of the following occur as part of angular context:

  • DOM Events (like ng-click etc.)
  • Ajax with callbacks ($http etc.)
  • Timers with callbacks ($timeout etc.)
  • calling $apply, $digest
  • etc.

It is important to note that the normal browser related DOM events (onclick etc.) and setTimeout would not trigger a digest process as they work out of "Angular Context".

I learnt the above from the following: Angularjs Digest Cycle - TechCBT

The above is a quick snapshot from a very in-depth tutorial available here: https://www.youtube.com/watch?v=SYuc1oSjhgY

Inspector answered 14/10, 2016 at 20:32 Comment(1)
This answer better address the questionDomination
G
3

Any AngularJS scope variable when handled from outside (including ajax) needs a $apply().

setTimeout is Javascript function So $apply is needed to update angularjs values.

$timeout is a angularjs function which returns promise and takes care of the current scope and runs in the same digest cycle.

So need not of $apply() function to update values.

Gerena answered 27/4, 2016 at 4:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.