32

I'm trying to write a small service in my angular app which will enable me to pick config parameters specified in global Javascript objects. I don't want to attempt accessing the global config object unless the document is ready (because I cannot guarantee the order in which script elements will be inserted in the HTML).

However, I can't understand why I need the call to $apply for the resolution to actually propagate to the then callback.

myModule.service('GlobalConfigService', ['$q', '$rootScope', function($q, $rootScope) {
    var def = $q.defer();
    $(document).ready(function() {
        def.resolve(MyConfig.val);
        $rootScope.$apply();
    });

    def.promise.then(function () {
        console.log('I am called only when $apply() is called. Why?');
    });

    return def.promise;
}]);
Saurabh Nanda
  • 6,373
  • 5
  • 31
  • 60

1 Answers1

33

In AngularJS the results of resolve() are propagated asynchronously, inside a $digest cycle, not immediately. This means that callbacks registered with then() will only be called (later) when a digest cycle occurs.

In your code, nothing is causing Angular to enter a digest cycle, so the then() callback is never called. Calling $apply() is one way to cause a digest cycle to run. Another way: add a button with ng-click that does nothing, then click that, it will cause a digest cycle and you should see the results:

<button ng-click="">Force digest by clicking me</button>

See also https://stackoverflow.com/a/14657974/215945

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492