trajce trajce - 1 year ago 87
Javascript Question

AngularJs $q.defer() not working

I had some problems with


When I used callbacks instead, my code was working(the view was updated), but with
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){
console.log('status: ', status, ' data: ', data);
error(function(data, status, headers, config){
console.log('status: ', status);
return deferred.promise;

The controller:

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:

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?

Answer Source

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:

  • Return an empty array.
  • Populate it later on when the request arrives.
  • Trigger a digest on its own.

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.


$ = $http({method: 'GET', url: '/someUrl'}); <p>{{foo}}</p>


$http({method: 'GET', url: '/someUrl'})

.success(function(data) { $ = data; });``



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.