I have a service that does something hard and returns a promise:
.factory('myService', function($q) {
return {
doSomethingHard: function() {
var deferred = $q.defer();
setTimeout(function() {
deferred.resolve("I'm done!");
}, 1000);
return deferred.promise;
}
};
})
I have a controller that adds a function to the scope using that service:
.controller('MyCtrl', function($scope, myService) {
$scope.doSomething = function() {
var promise = myService.doSomethingHard();
promise.then(function(result) {
alert(result);
});
};
})
I use a directive to call that controller function by parsing an attribute:
.directive('myDirective', function($parse) {
return {
link: function(scope, el, attr) {
var myParsedFunction = $parse(attr.myDirective);
el.bind('click', function() {
myParsedFunction(scope);
});
}
};
})
with the template
<div ng-controller="MyCtrl">
<button my-directive="doSomething()">The Button</button>
</div>
Clicking the button triggers the event listener, which calls the controller function doSomething
, which calls the service function doSomethingHard
, which returns a promise, THAT IS NEVER RESOLVED.
Whole thing up on a fiddle here:
http://jsfiddle.net/nicholasstephan/RgKaT/
What gives?
Thanks.
EDIT: Thanks to Maksym H., It looks like wrapping the promise resolve in $scope.$apply()
makes it fire in the controller. I've got a working fiddle up http://jsfiddle.net/RgKaT/4/. But I'd really like to keep the scope out of my services.
I'd also really like to know why this works. Or better yet, why it doesn't work without resolving the promise while wrapped in a scope apply. The whole Angular world vs regular Javascript world analogy makes sense when thinking about properties as changes need to be digested, but this is a promise... with callback functions. Does $q just flag the promise as resolved and wait for the scope to digest that property update and fire its resolved handler functions?