1

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"})
    }
}
useyourillusiontoo
  • 1,287
  • 1
  • 10
  • 24
  • 2
    Avoid the [deferred antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Jun 26 '17 at 20:00
  • The second parameter of `.then()` is the failure/reject callback. – mhodges Jun 26 '17 at 20:00
  • You can just `throw` or return a rejected promise in any `then` callback. – Bergi Jun 26 '17 at 20:02
  • throw is no good in this case, I need to collect the rejected data in the $stateChangeError listener. Am aware of the antipattern but got desperate and trying everything possible. – useyourillusiontoo Jun 26 '17 at 20:15
  • @Bergi How are you suggesting I reject the promise in an external function? $q.reject() don'twork – useyourillusiontoo Jun 26 '17 at 20:17
  • @useyourillusiontoo It does work, you just need to `return` it. And if you need to collect the error data, just handle it in a `.catch()` callback or do some side effects before throwing. – Bergi Jun 26 '17 at 20:20
  • @Bergi It honestly doesn't, i'm getting: ReferenceError: $q is not defined – useyourillusiontoo Jun 26 '17 at 20:24
  • @useyourillusiontoo Well that's just a DI problem with `$q`, not that returning rejected promises from callbacks wouldn't work. – Bergi Jun 26 '17 at 20:25
  • @useyourillusiontoo Or, if you're referring to the code in the question, just a typo: it should be `this._$q` instead of `this_.$q` (and of course you need to bind methods that you pass as callbacks) – Bergi Jun 26 '17 at 20:27
  • @Bergi And therein lies the problem! I understand the promise theory. (its a typo on this._$q – useyourillusiontoo Jun 26 '17 at 20:27

0 Answers0