udpmtq
Last Updated: September 22, 2018
·
333.1K
· otupman

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

16 Responses
Add your response

4688

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

over 1 year ago ·
4761

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

@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

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

Great tip!

over 1 year ago ·
10725

As of 1.2 they will have $interval :)

over 1 year ago ·
14747

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

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

Thank you! :)

over 1 year ago ·
28619

$interval is now available for those that want to use setInterval: https://docs.angularjs.org/api/ng/service/$interval

over 1 year ago ·
29369

"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)."

Awesome, thank you buddy! Helped me a lot!

11 months ago ·
29509

Good project!

9 months ago ·
29775

Nice Good job. Thanks for sharing greart information. Learn and become Master in AngularJS here: https://mindmajix.com/angularjs-training

6 months ago ·
29981

Thank you for this information. And this article may be some what usefull to get some more knowledge
https://tekslate.com/directives-in-angularjs/

3 months ago ·
30312

I 'm đánh giá cao post your blog, it or or very help for the job of me. Thank you.
http://ducklifeonline.com

about 1 month ago ·