AngularJS – $$postDigest vs $timeout when DOM update is needed

April 8, 2014

2 comments

When you need to update the DOM once after dirty checking is over or in other words, fire a callback after the current $digest cycle completes,
you can use $$postDigest or $timeout.
I’ll try to explain the cons and the pros of  $$postDigest and $timeout.

$$postDigest 

pros:

         1. Fires a callback after the current $digest cycle completes.

         2. Great for updating the DOM once after dirty checking is over.

cons:

         1. $$ means private to Angular, the interface is not stable.

usage:

//runs immediately after $scope.$digest

$scope.$$postDigest(function(){

  console.log("post Digest");

 });

* it should be noted that $$postDigest wont run another digest cycle.

$timeout 

pros:

         1. Runs after the current $digest cycle completes.

         2. Great for updating the DOM once after dirty checking is over.

cons:

         1. a little more complex to use.

usage:
to prevent another digest cycle to run by default ,we need to set the third argument to false.

//runs immediately after $scope.$digest

$timeout(function(){

 console.log("post Digest with $timeout");

},0,false);

Live example:

so in conclusion, the “Angular way” to make DOM updates after digest cycle, is by using a $timeout service because:
A) The interface is public, means there wont be any surprises.
B) although it’s a bit more complex to use, in the long run, $timeout has more rich API to offer.

Reference:
https://docs.google.com/presentation/d/15XgHRI8Ng2MXKZqglzP3PugWFZmIDKOnlAXDGZW2Djg/edit#slide=id.p

http://docs.angularjs.org/api/ng/service/$timeout

 

Hope you’ll find this post helpful.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

2 comments

  1. Scott SilviAugust 18, 2014 ב 21:32

    You shouldn’t use $$postDigest here.

    Another option is to use $evalAsync. It’s similar to $$postDigest in that it defers execution of the function & is only called once. It differs in that you’re not using an “internal API”, and evalAsync will also trigger a $digest if one is not already in process. $evalAsync will always be called during the current digest (but after the watcher iterations), or at the very beginning of the next digest, so it will still do what you want.

    The benefits to using $evalAsync over $timeout is that you don’t end up deferring the timing of when your code is called to the browser event loop. You also get to update the DOM before the browser has, so you don’t have to rerender the DOM (both expensive, and potential for content flickering).

    Here’s some details on the differences:

    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)

    Reply
    1. Jack A.August 29, 2014 ב 22:04

      Using $evalAsync is really not equivalent to either $$postDigest or $timeout. Any $evalAsync callbacks are fired at the start of the next $digest iteration, so cascading changes (any change that requires multiple $digest iterations to be applied) will not be seen by your callback.

      Both $$postDigest and $timeout callbacks get executed after all iterations of the $digest cycle are completed.

      Reply