Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between $evalAsync and $timeout in AngularJS?

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.

like image 586
dnc253 Avatar asked Jun 25 '13 15:06

dnc253


People also ask

What is $timeout in AngularJS?

This '$timeout' service of AngularJS is functionally similar to the 'window. setTimeout' object of vanilla JavaScript. This service allows the developer to set some time delay before the execution of the function.

What is evalAsync?

$evalAsync([expression], [locals]);Executes the expression on the current scope at a later point in time. 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).

What is the function of the $timeout service?

The $timeout service can be used to call another JavaScript function after a given time delay. The $timeout service only schedules a single call to the function. For repeated calling of a function, see $interval later in this text.


2 Answers

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)
like image 162
Mark Rajcok Avatar answered Oct 11 '22 02:10

Mark Rajcok


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.

like image 34
floribon Avatar answered Oct 11 '22 01:10

floribon