What's the difference between $evalAsync and $timeout in AngularJS?
Solution 1:
I recently answered essentially this question here: https://stackoverflow.com/a/17239084/215945 (That answer links to some github exchanges with Misko.)
To summarize:
- if code is queued using $evalAsync from a directive, it should run after the DOM has been manipulated by Angular, but before the browser renders
- if code is queued using $evalAsync from a controller, it should run before the DOM has been manipulated by Angular (and before the browser renders) -- rarely do you want this
- if code is queued using $timeout, it should run after the DOM has been manipulated by Angular, and after the browser renders (which may cause flicker in some cases)
Solution 2:
For those building complex applications, be aware that there is a performance impact on your choice. Also, I would like to complete Mark answer with more technical details:
$timeout(callback) will wait for the current digest cycle to be done (i.e. angular update all model and the DOM), then it will execute its callback - potentially affecting angular model - then launch a full
$apply
on the root $scope, and redigest everything.$evalAsync(callback), on the other hand, will add the callback to the current, or next, digest cycle. Which means if you are within a digest cycle (for instance in a function called from some
ng-click
directive), this will not wait for anything, the code will be executed right away. If you are within an asynchronous call, for instance asetTimeout
, a new digest cycle ($apply
) will be triggered.
So in terms of performances it is always better to call $evalAsync
, unless it is important for you that the view is up to date before executing your code, for instance if you need acces to some DOm attribute such as elements width and the like.
If you want more details about the distinction between $timeout, $evalAsync, $digest, $apply, I invite you to read my answer on that other question: https://stackoverflow.com/a/23102223/1501926
Also be sure to read the documentation:
The $evalAsync makes no guarantees as to when the expression will be executed, only that:
- it will execute after the function that scheduled the evaluation (preferably before DOM rendering).
- at least one $digest cycle will be performed after expression execution.
Note: if this function is called outside of a $digest cycle, a new $digest cycle will be scheduled. However, it is encouraged to always call code that changes the model from within an $apply call. That includes code evaluated via $evalAsync.