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.
Related
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.
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.
What is the difference between $evalAsync and $applyAsync? My understanding is that when I use $evalAsync from a directive, the expression will evaluate before the browser renders.
So as an example, if I wanted to scroll to a particular position on a page but not show the jump to that spot, I could use this to scroll to the position and since it fires before the browser has rendered, this visual bug would be gone.
However, what is the purpose of applyAsync? When is it a good idea to use one over the other?
The
$evalAsync()
will execute in the current digest
$applyAsync()
in a scheduled one.
If you need details:
Ben Nadel or stack here
Here is what I have been using $applyAsync for. Basically, I use this as a safe $apply. You know that annoying error when you try to trigger a digest when one is already in progress? If you use $applyAsync, you will get another digest, but it will occur when the current digest cycle has completed.
$applyAsync is also cool since you can batch up a bunch of callbacks to fire within then next digest.
In the angular scope, I have a huge object scope.a, and somehow I have another scope.b reference to it.
I know angularJS uses dirty checking, so we should reduce the stuff inside scope. My question is, since a and b are essentially the same obj(reference). Will it have noticeable performance improvement if I manage to get rid of b, keep only one reference?
Just having something in the scope does not have any performance implications on the $digest cycle (See Integration with the browser event loop here: https://docs.angularjs.org/guide/scope).
The dirty checking ($digest cycle) calls any registered $watch functions (manually registered in your code or registered in the angular code), and then calls the listener function if the $watch function returned anything different from last time.
To answer your question, no there won't be any performance improvement by not adding something to the scope. Performance is most readily improved by improving performance of any $watch functions, since they are always called at least once every $digest cycle.
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.