Are digest cycle and digest loop identical? - angularjs

I was going through digest cycles (and loops) and getting to know about $apply, $digest and so on. However, in some articles they refer digest cycles the same as digest loops. I know that there will be at least two iterations for any $apply. What are those iterations called (digest cycles or digest loops).
If they are different, are they related? If so, how?

They are the same - it is the background process AngularJs uses to detect changes.

Related

How to find out what exactly triggers digest cycle in AngularJS

I encountered performance problems with my AngularJS application on IE and started analyzing the root cause for this. The root cause seems to be, that too many watchers are used, ng-repeat is used for a table with a large amount of data, almost no one-way-data-binding is being used and static data is not being cached. So in general I found out, that it's not just an IE problem.
However, I also started to analyze the digest circle and tried to keep track of it:
$rootScope.$watch(function () {
count += 1;
console.log('Count: ', count);
});
According to my console output, the digest cycle triggers every 1s.
This is very, very problematic in my eyes, because from what I have read so far it should only trigger in certain cases and not continuously. Well, there is a timed request for data, but it's only every 10 seconds...but maybe some change triggers another and so on.
I would like to find out which part of my code triggers the digest cycle, is there a way to do this?
Thanks in advance
Update
The problem was not caused by the view containing the table, I found a hidden
$interval(function () { ... }, 1000)
somewhere else, which causes the digest cycle to trigger every second.

Suspend digest loop until ngReapeat has finished initial rendering

I want to know if and how it is possible to suspend digest loops until my array of objects have finished the initial rendering.
I have custom templates defined by the objects they receive, the array is dynamic therefore I'm using ngRepeat. The issue I'm having is that every digest loop takes around 15ms in IE11, but I can have 100-200 templates being rendered, which can add up to ~2000ms.
Is there a way to suspend actual digest loop in ngRepeat from outside, or do I have to decorate the directive itself to achieve that?
Note: Generally other browser are really good with performance and we don't have any issues, but IE11 is a special case and we need every single performance gain we can.

Does $evalAsync makes $scope.$apply unnecessary?

From my understanding, $evalAsync will queue the changes to the current digest cycle if it can, if not then to the next one.
So in which cases would i use $scope.$apply ?
Both of them run digest on the $rootScope, but $evalAsync have the possibility to make it faster by hooking into the current digest cycle, which sounds better in 99% cases.
I have seen this info below link , I felt good may it will useful to you !
http://www.codingeek.com/angularjs/angular-js-apply-timeout-digest-evalasync/
$evalAsync() is a new function which was first introduced in AngularJS 1.2.X, and in my opinion it is the adroit version of $timeout().
Before $evalAsync() came into the picture, AngularJS team recommended using the $timeout() in case of digest cycle issue, described above.
As AngularJS evolved for large apps and digest cycle became common and then Angular team introduced $evalAsync(). This function will evaluate the expression during the current cycle or the next.
Suppose you call some expression on $evalAsync() and any digest cycle is going on at the same time. All expressions from $evalAsync() will be added to the queue and they will be part of the current lifecycle and no new digest cycle will be invoked. This is why $evalAsync() make it more efficient because it reduce the possibility to create new digest every time.
If there is not any digest is going on, it will work similar to $timeout. It will create a callback with default time (10 ms) and after this time (10 ms), there will be a new digest on rootScope and all expressions will be evaluated.

How to check whether current digest has finished as "clean" and will not trigger another digest loop

The subject stands for the question itself, is there a way in angular to check whether current digest cycle has been completed as the last one and the model has been settled and current digest cycle itself will not trigger another digest cycle
I understand that the digest cycle can be triggered by user code or as a result of user's interaction with the browser. In any way angular knows when to stop digesting deeper and deeper.
You should try scope.$$postDigest or $timeout(..., 0, false).
Here is a good summary on both methods.

How are watchers and filters treated within the AngularJS digest loop?

I understand that both scope watchers and filters are executed repetitively within the digest loop. However the following is a bit unclear to me:
Are they executed the same amount of cycles?
Are both triggered by the same circumstances?
Watches are checked every digest cycle. And a $watch can watch an Angular expression. Inside an expression there can be a filter which Angular must evaluate (using $interpolate) to decide if the watched expression has changed.
Are both triggered by the same circumstances?
So, filters aren't run directly by $digest but are rather run as a consequence of a $watch. In effect, filters are triggered by the evaluation of watched expressions.
There's a few reasons filters get talked about specially with regard to the performance of $digest. Looking at these two expressions:
Expression 1: {{searchText+2}}
Expression 2: {{searchText | myFilter:true}}
Both expressions will be evaluated everytime a $digest is triggered. So one risk area is simply that myFilter could be complex and end up using a lot more processor cycles than something simple (like the above +2).
A bit less obviously, a filter can cause extra runs of all watchers if it's not idempotent. On each run of $digest a dirty bit is set if any of the watches results in a change. And it reruns all the watches again if that dirty bit is set. This allows any changes to be propagated. For instance if searchText is changed by one of the watches then Angular needs to give all the other watchers a chance to see if their results depend on searchText and thus should change.
Herein lies the difference between expressions 1 and 2 above. As a worst case scenario imagine myFilter returns a random number. $digest runs, sees a change when evaluating the watches (the previous result of the filter doesn't match the new result) so it runs through the watch list again. Because the filter returns a random number it's results have very likely changed, triggering yet another run of $digest. etc, etc... Angular has a built in stop after 10 loops through it's watch list- it figures if the results don't stabilize after 10 tries then something is wrong and so it gives up throwing "Error: 10 $digest() iterations reached. Aborting!"
Are they executed the same amount of cycles?
Therefore at a minimum each watched expression (including any filters) is run twice per $digest. Once because of the change that triggered $digest and once more to check if that result needs to propagate. If that propagation resulted in any changes then the watches and filters will be run again until nothing changes.
And, of course, if multiple watched expressions use the same filter then that filter will be run, following the above, for each expression.

Resources