I\'ve been using AngularJS for a little while now, and have found the need to use $timeout every once in a while (Seems to usually be to init a jQuery plugin).
Recently, I\'ve been trying to get a better and more in-depth understanding of the digest cycle, and I came across $evalAsync function.
It seems like that function produces similar results to $timeout
, only you don\'t give it delay. Every time I\'ve used $timeout
it has been with a delay of 0, so now I\'m wondering if I should have used $evalAsync
instead.
Are there any fundamental differences between the two? What cases would you use one over the other? I\'d like to get a better feeling of when to use which one.
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)
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 a setTimeout
, 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.