Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 634
luisfarzati Avatar asked Jan 31 '26 00:01

luisfarzati


1 Answers

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.

like image 92
KayakDave Avatar answered Feb 02 '26 16:02

KayakDave



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!