Where developers come to connect, share, build and be inspired.


AngularJS: use $timeout, not setTimeout


There are some cases where one needs to perform some sort of timeout operation and we frequently achieve this using JavaScript's setTimeout() function.

However, if we use setTimeout() in an AngularJS application we also need to use $scope.$apply() to ensure that any changes to the scope will be reflected elsewhere (i.e. data-bound in a view).

AngularJS provides a handy wrapper for this: $timeout() - it does the $apply() call for us so we don't have to. Magic!

function Ctrl($scope, $timeout) {
    $scope.timeInMs = 0;

    var countUp = function() {
        $scope.timeInMs+= 500;
        $timeout(countUp, 500);

    $timeout(countUp, 500);

And here's a JsFiddle showing it working: http://jsfiddle.net/otupman/fq4vg/

Update and warning- if you're using $timeout to create what is essentially an interval; don't - it will break your e2e tests :( The workaround is to set the standard setTimeout for the moment :( :( :(

More info on the Angular github issue here: https://github.com/angular/angular.js/issues/2402


  • 2013-4-6-prof

    $timeout is really handy indeed! I'd also like to see $interval alongside $timeout.

  • 45975fcc42c585f7ddd9711e1f5198a7

    Agreed! If I get the chance I might look into that, though I do think someone else must have written one.... maybe :D

  • 2013-4-6-prof

    @otupman Yeah, all kinds of hackish workarounds can be spotted out there in the wild: http://stackoverflow.com/a/14238039/1809349

  • User-avatar

    Oh wow, I just posted a similar tip after suffering thru a setTimeout() issue for a while on Friday. Wish I had seen this tip on Thursday :D

  • 3f23a52c7bc87296e96b5a05547da0e0

    Yeah there are a couple of $interval implementations kicking around, with various degrees of success.

    Hoepfully it'll be standard soon.

  • 98aba6d508f3f1e7fd6b21e8bfdb6b6c

    Great tip!

  • Kong

    As of 1.2 they will have $interval :)

  • Ed7df36217d754e6eac169f0b38a8500

    Just out of interest, can you use $digest straight after changing a scope value instead of wrapping it all in an $apply function? Or does that not work?

  • Me

    You can use $digest if the $scope data being watched is on the current $scope or child $scopes. A $digest will trigger all the $$watchers down the tree, but won't propagate to sibling or parent $scopes. Use $apply if you want all $$watchers to trigger on the $scope tree.

    Also, as noted above, $interval and $timeout trigger $apply, and there are definitely times where you'll want to use a timeout or interval function that isn't changing $scope data. Don't bog down your application by triggering unnecessary $$watches, - know when to use $timeout/$interval and setTimeout/setInterval.

Add a comment