Angular: why isn't $evalAsync called $applyAsync?
Asked Answered
E

2

6

Angular beginner question about scopes (docs here).

  1. $eval executes an expression in the context of a scope.
  2. $apply basically calls $eval and then $digest.
  3. Why does $evalAsync call $digest too (or, more precisely, ensure $digest is called)?

It seems to be that $evalAsync should really be called $applyAsync, doesn't it?

I'm a beginner -- what am I missing?

Espalier answered 31/1, 2014 at 2:17 Comment(2)
Take a look here for some nice explanation of $evalAsync/$eval/$digest/$applyPonderable
@Ponderable That's actually the article where I'm coming from and still didn't get it. Sorry I'm a noob!Espalier
G
3

$evalAsync and $applyAsync target to different situations.

$evalAsync: defers the expression to the next loop iteration of current digest cycle. One Angular digest cycle loops for a few times until no data is dirty. If no digest cycle is in progress, it will start a new digest cycle (call $apply method) and evaluate the expression (call $eval method) in it. This method is useful if you call a function out of Angular scope but still like to digest the dirty data when a digest cycle is already in progress, in which case you cannot call $apply.

$applyAsync: defers the expression to the next cycle of digest. It always starts a new cycle of digest to after the expression is evaluated (call $apply method). This method is useful if you frequently execute some service call back (like $http service) out Angular scope with dirty scope data. However, if it starts a digest for each callback, there may be bad performance. Therefore, this method optimize the process by share the digest cycles among several async callbacks, which outperforms the method $evalAsync.

Gunboat answered 8/4, 2016 at 6:54 Comment(0)
J
2

$applyAsync already exists:

Schedule the invocation of $apply to occur at a later time. The actual time difference varies across browsers, but is typically around ~10 milliseconds.

This can be used to queue up multiple expressions which need to be evaluated in the same digest

evalAsync handles digests differently:

$evalAsync triggers a digest, and is unsuitable when it is expected that a digest should not occur.

Note: if this function is called outside of a $digest cycle, a new $digest cycle will be scheduled.

This behavior of this when called implicitly changed in AngularJS 1.3:

-Previously, even if invokeApply was set to false, a $rootScope digest would occur during promise resolution. This is no longer the case, as promises returned from $timeout and $interval will no longer trigger $evalAsync (which in turn causes a $digest) if invokeApply is false.

Workarounds include manually triggering $scope.$apply(), or returning $q.defer().promise from a promise callback, and resolving or rejecting it when appropriate.

References

Janetjaneta answered 22/12, 2014 at 7:42 Comment(3)
according to ben nadals eximination (bennadel.com/blog/…) both do the same thing, just the timing is differentHyalite
@Hyalite No. Ben mentions that asynchronous expressions added by $evalAsync() from within a $watch() binding will execute in the same digest. Asynchronous expressions added by $applyAsync() from within a $watch() binding will execute at a later point in time (~10ms).Janetjaneta
@ Yes you are right the $evalAsync() will execute in the current digest $applyAsync() in a different one i was mainly objecting to your corrected statement of ".., while $evalAsync interprets expressions" which might have been misleading. Since you took it out i take back my vote down :)Hyalite

© 2022 - 2024 — McMap. All rights reserved.