Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

angularjs

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; }]); 
like image 336
Saurabh Nanda Avatar asked Feb 07 '13 07:02

Saurabh Nanda


People also ask

What is $apply in AngularJS?

In AngularJS, $apply() function is used to evaluate expressions outside of the AngularJS context (browser DOM Events, XHR). Moreover, $apply has $digest under its hood, which is ultimately called whenever $apply() is called to update the data bindings.

What is deferred resolve in AngularJS?

The relationship between the defer object and its promiseto return a value on successful receipt of asynchronous information, you'd call defer. resolve() , which, in turn, will call its promise's then() function. if you call defer. reject() , the promise's catch() function will be called. call defer.

What is resolve in AngularJS?

A resolve is a property you can attach to a route in both ngRoute and the more robust UI router. A resolve contains one or more promises that must resolve successfully before the route will change.

What is promises in AngularJS?

Promises in AngularJS are provided by the built-in $q service. They provide a way to execute asynchronous functions in series by registering them with a promise object. {info} Promises have made their way into native JavaScript as part of the ES6 specification.


1 Answers

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

like image 69
Mark Rajcok Avatar answered Oct 13 '22 06:10

Mark Rajcok