I had some problems with $q.defer();
When I used callbacks instead, my code was working(the view was updated), but with $q.defer();
it's not.
This is my code:
The service:
eventsApp.factory('eventData', function($http, $q) {
return {
getEvent: function(callback) {
var deferred = $q.defer();
$http({method: 'GET', url: '/node/nodejsserver/server.js'}).
success(function(data, status, headers, config){
//callback(data.event);
deferred.resolve(data.event);
console.log('status: ', status, ' data: ', data);
}).
error(function(data, status, headers, config){
deferred.reject(status);
console.log('status: ', status);
});
return deferred.promise;
}
};
});
The controller:
eventsApp.controller('EventController',
function EventController($scope, eventData) {
$scope.event = eventData.getEvent();
}
);
But it doesn't work.
Then I found this answer and I updated my controller like this:
eventsApp.controller('EventController',
function EventController($scope, eventData) {
eventData.getEvent().then(function(result) {
$scope.event = result;
});
}
);
and it works.
What is the difference between the nonworking and the working code?
$q. defer() allows you to create a promise object which you might want to return to the function that called your login function.
$q is integrated with the $rootScope.Scope Scope model observation mechanism in AngularJS, which means faster propagation of resolution or rejection into your models and avoiding unnecessary browser repaints, which would result in flickering UI.
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.
then() function to handle the callbacks. Traditional promises (using the $q Service in Angular) have a . then() function to provide a continuation on success or failure, and . then() receives parameters for a success and failure callback.
The non working code uses automatic promise unwrapping which was deprecated and removed in recent versions of Angular. It was deemed too magical.
Angular used to do the following when you returned a promise:
This behavior was deemed confusing and magical by Angular developers and was deprecated (in 1.2), deactivated and soon (1.3) removed in Angular. The correct way to assign a value through a promise is like you've indicated in the second example:
eventData.getEvent().then(function(result) {
$scope.event = result;
});
From the Angular 1.3 (pending) release docs:
$parse: due to fa6e411d, promise unwrapping has been removed. It has been deprecated since 1.2.0-rc.3. It can no longer be turned on. Two methods have been removed:
And from the 1.2 release docs:
$parse and templates in general will no longer automatically unwrap promises.
Before:
$scope.foo = $http({method: 'GET', url: '/someUrl'});
<p>{{foo}}</p>
After:
$http({method: 'GET', url: '/someUrl'})
.success(function(data) {
$scope.foo = data;
});``
{{foo}}
`This feature has been deprecated. If absolutely needed, it can be reenabled for now via the $parseProvider.unwrapPromises(true) API.
While we're here avoid the deferred anti pattern, $http
already returns the promise so you can simply return
it rather than using $q.defer
.
Edit: check Benjamin's answer
In your service, you are returning a promise
object, promise object has .then
method.
you are assigning the promise
object to $scope.event
, so you wont get the data (in the latest version according to Benjamin)
when you resolve the promise using deferred.resolve(data.event)
then the function you passed as argument to .then
method will be called with this resolved data.
You can give a second argument to the .then
, which will be called when you do deferred.reject()
This is basic functionality of promise api. Just read the docs for more info https://docs.angularjs.org/api/ng/service/$q
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With