udpmtq
Last Updated: November 27, 2016
·
173.5K
· otupman
45975fcc42c585f7ddd9711e1f5198a7

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

10 Responses
Add your response

4688
2013 4 6 prof

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

over 1 year ago ·
4761
45975fcc42c585f7ddd9711e1f5198a7

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

over 1 year ago ·
4778
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

over 1 year ago ·
6206

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

over 1 year ago ·
7226
3f23a52c7bc87296e96b5a05547da0e0

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

Hoepfully it'll be standard soon.

over 1 year ago ·
8007
98aba6d508f3f1e7fd6b21e8bfdb6b6c

Great tip!

over 1 year ago ·
10725
Kong

As of 1.2 they will have $interval :)

over 1 year ago ·
14747
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?

over 1 year ago ·
16166
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.

over 1 year ago ·
28346
Foto el 26 11 16 a las 1.45 a.m.

Thank you! :)

5 days ago ·