1

I've been looking into the caveats of the AngularJS Digest cycle and I would like to better understand where the separation is between using it properly and improperly.

For example, if I have an AngularJS code that looks like this:

var myApp = angular.module("testApp", []);

myApp.controller("testController", ["$scope", "$timeout", function($scope, $timeout){
    setTimeout(function(){
        $scope.username = "Test User name";
    }, 3000);

    $timeout(function(){
        $scope.username = "AngularJS User name";
    }, 3000);
}]);

Why is setTimeout not being used as part of the Digest Cycle, whereas $timeout is, and how can I fix this to work?

Please keep in mind, I am looking not only for a code solution but for an explanation of why this occurs. As good as a code solution may come, it will not explain itself.

7
  • setTimeout isn't part of angular and therefore doesn't trigger change detection. The solution for that is $timeout, what's left to explain? Commented Feb 15, 2016 at 19:59
  • @LukaJacobowitz I just don't understand why that would be, when AngularJS typically wraps your code in a $scope.$watch function, yet despite that it does not look within setTimeout. Commented Feb 15, 2016 at 20:00
  • 1
    setTimeout is just a plain javascript function so angular cannot $watch it. Commented Feb 15, 2016 at 20:02
  • 1
    @LukaJacobowitz is this the case for all other plain javascript functions as well? Meaning if I meant to use one with the digest cycle, I must ensure that AngularJS knows about them? Commented Feb 15, 2016 at 20:03
  • Yes, indeed, it's a common mistake for people coming from jQuery to wonder why changes aren't detected when they call jQuery functions. Commented Feb 15, 2016 at 20:04

3 Answers 3

1

$timeout is an angularized version of setTimeout(), i.e. it is coded in such a way that it triggers a digest cycle. setTimeout() is a plain Javascript function that knows nothing about Angular or a digest cycle. Since setTimeout() is not a simple JS object, Angular cannot $watch it.

So the whole point of having functionality like $timeout is that they are angular-friendly versions of some Javascript functionality.

Sign up to request clarification or add additional context in comments.

4 Comments

Interesting, so any other functions that are native to javascript and have not been angularized will also be subject to such? Meaning I should be looking for the service version of it and expect it to work in the angular way?
Typically, other JS functions are free of effects that would trigger a digest cycle. DOM manipulation functions would be different, that's why you should not use JS or native DOM manipulation but leave that to Angular and its templating (which of course knows about the digest cycle) or use the angularized angular.element methods. Things like array manipulation which change the model and therefore should trigger a digest are taken care of by the $watch functionality built into Angular that guards properties of the $scope object
Ok so plain JavaScript functions in general, used within AngularJS, are only safe to use for scope or DOM manipulation as long as they are in line with what AngularJS is doing on top of them. I get it now.
That's the general idea, yes.
1

$timeout() and setTimeout() are not the same, $timeout is angularised.

It uses promise ($q service) internally, which would resolve after every digest cycle, automatically. Whereas setTimeout(), is just a trick with registering your callback function in the queue.

If you want setTimeout() to be part of digest loop, call it within the $scope.$apply():

setTimeout(function(){
    $scope.$apply(function(){
        $scope.username = "Test User name";
    });
}, 3000));

1 Comment

Thanks for the explanation, I modified your answer to correctly use$scope.$apply
1

A more generic explanation is that setTimeout does not work inside of angular because it puts its callback on the event loop, which angular does not watch. The same situation would happen if you were to create an XMLHttpRequest directly instead of $http.

Angular has made their own abstraction of these utilities/objects so that when they finish, the digest cycle will pick up any changes.

2 Comments

That's a better version of a generic explanation, especially when considering the AngularJS digest cycle vs the JavaScript native event loop, big difference yet invisible to the naked eye
@AGE better enough that I get the green check? :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.