AngularJS – why is $apply required to properly resolve a $q promise?

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;
}]);

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

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

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply