Assume that we have a bit of html like that:
<button
id="my-login-button"
ng-hide="loggedIn"
ng-click="login()">Log me in!</button>
Also we have a JavaScript:
// controller.js
$scope.login = function () {
API.login()
.then(function () {
console.log('login promise resolved');
});
};
// service.js
app.factory('API', ['$q', '$timeout', function ($q, $timeout) {
return {
login: function () {
var login = $q.defer();
// async login
VK.Auth.login(
function () {
// login.resolve(); // doesn't work without $timeout()
$timeout(login.resolve); // works as it should
},
VK.access.FRIENDS | VK.access.AUDIO
);
return login.promise;
}
};
}]);
This piece of code works properly, but the mysterious part is near the $timeout()
function. Why I should wrap my resolving with it? Why code doesn't work as expected without it?
I don't do something with scope variables, I'm just consoling. And without $timeout
it will be called with next digest...
As for me it have no sense, if I need to change scope props, I will wrap everything in $apply
.
Could anyone explain why usual deferred behavior became mysterious one?
P.S. I've solved my issue with $timeout
after reading this question answers.
In AngularJS promise results are propagated asynchronously, inside a $digest cycle. So, the results of then() are not propagated until the next digest cycle, which never comes without a $timeout
or $http
or $apply
to trigger one.