I'm currently building a service in angularJS (v1.4.14) using the new ES6 class syntax and have a chained/flattened promise tree with 3 .then()'s
The setCampaign() method is being resolved on a state by ui-router. When there if a problem with the data (such as no id field in example below) I want to reject the promise so that the routers '$stateChangeError' listener picks up the rejected object and redirect to the error state.
I'm struggling with how to reject the promise (and break the chain) if something goes wrong.
I know I can use $q.reject if I don't extract my handlers to different method names like so:
setCampaign(){
  let deferred = this._$q.defer();
  this._ApiService.get({entity: 'campaign'}).$promise.then(
    campaignResponse => {
        if (campaignResponse.status == 'success' && campaignResponse.data.id){
            //assign to the campaign property and return to next .then()                
            this.campaign = campaignResponse.data
            //call next promise
            this.Api.get({entity: 'campaign-info', entity_id: campaignResponse.data.id }).$promise.then(
                //handle response and get forever more indented ugly code
                campaignInfoResponse => {
                    //do more stuff ...
                    return deferred.resolve(data);
                }
            )
        }
        //break the chain
        return deferred.reject(({status:"error", message: "blah blah"})
    });
  return deferred.promise
}
But I want to write code that isn't indented to the millionth degree and looks more elegant. When I do this I seem to be unable to reject the promise. Can anybody help?
class CampaignService{
    constructor($q, ApiService){
        'ngInject';
        this._$q = $q;
        this._ApiService = ApiService;
    }
    setCampaign(){
        return this._ApiService.get({entity:'campaign'})
            .then(this.assignCampaign)
            .then(this.getCampaignTheme)
            .then(this.assignTheme)
            .catch(this.errorHandler);
    }
    assignCampaign(campaignResponse){
        if(campaignResponse.status == 'success' && campaignResponse.data.id){
            //assign to the campaign property and return to next .then()
            this.campaign = campaignResponse.data
            return campaignResponse.data
        }
        //break the chain
        return this._$q.reject({status:"error", message: "blah blah"})
    }
}
