Resolving promises on resolver using ui-router We're rewriting some parts of our application. We're trying to avoid the promise anti-pattern and do things properly, but I'm not certain that we did so.

More precisely, we are rewriting the resolver of a state using ui-router.

.state( 'catalogue', {
  // skipped on purpose not relevant content
  resolve : 
    boxCreateData : function( $stateParams, $q, Basket, Customer ) {

      var defer = $q.defer(),
          basket = null,
          customer = null;

      Basket.fromApi( $stateParams.id )
        .then( function( basket ) {
          Customer.fromApi( basket.getCustomer() )
            .then( function( customer ) {
              defer.resolve( { basket : basket, customer : customer } );
            });
        });

      return defer.promise;

    }
});


Basket.fromApi and Customer.fromApi are static methods of their corresponding "class"es, Basket and Customer. Both implementations are like this (more or less; it's not the whole code, but it shows the concept. Customer.fromApi is the same):

Basket.fromApi = function( id ) {
  var defer = $q.defer();
  boxesResource.get( { id : id }, function( response ) {
    // various manipulation here with the response...
   defer.resolve( new Basket( ... ) );
  });
  return defer.promise;
};


Note we are using the get method of $resource.

The major issue here is that until we have the basket, we can't query the customer (because customer ID comes in the basket object).

We are querying first the basket with the basket ID. Once we have it, we can get the customer ID from the basket object and then, retrieve the customer object.

I just don't like the then pyramid. I'm not sure if we are missing something or in this case, there is no other way to do it.

Is there a cleaner way to accomplish the same thing?
You shouldn't use $q.defer unless you have to. 

Here you can just return the promise:

Basket.fromApi = function (id) {
    return boxesResource.get({
        id: id
    }, function (response) {
        // various manipulation here with the response...
        return new Basket(...));
    });
};


You could really clean up the resolve by creating a new service:

State

.state('catalogue', {
    resolve: {
        boxCreateData: function($stateParams, boxCreateService) {
             return boxCreateService.getBoxCreateData($stateParams.id);
        }
    }
})


Service

app.service('boxCreateService', function(Basket, Customer) {
    this.getBoxCreateData = function(id) {
        return Basket.fromApi(id)
                .then(function (basket) {
                    return Customer.fromApi(basket.getCustomer())
                        .then(function (customer) {
                            return {
                                basket: basket,
                                customer: customer
                            };
                    });
                });
    };
});


There's not much you can do to avoid two nested promises here. You need the customer ID before you can get the customer. 

More on the deferred antipattern.