Save handler without a nested "deferred antipattern" I have an application in which a user makes a change, and when they click Save they will be prompted to confirm, and the appropriate REST call will be made if they agree. The intial call to Save() returns a promise that is fulfilled if the call returned successfully, or rejected if there was an error or the user canceled the confirmation.

I've boiled my actual implementation down to an equivalent example in order to highlight the (anti)pattern:

//assume confirm() and commit() are functions that return a promise:
//confirm() will be fulfilled or rejected based on a user choice
//commit() will be fulfilled or rejected based on the response from a RESTful web call

function save() {
    var deferred = $q.defer();

    confirm().then(function(response) {
        commit().then(function(response) {
            deferred.resolve();
        }).catch(function(rejection) {
            deferred.reject(rejection);
        });
    }, function(rejection) {
        deferred.reject(rejection);
    });

    return deferred.promise;
};


This stuck out to me rather clearly as the deferred antipattern, and so I refactored it to this:

function save() {
    var deferred = $q.defer();

    confirm().then(function(response) {
        deferred.resolve(commit());
    }, function(rejection) {
        deferred.reject(rejection);
    });

    return deferred.promise;
};


Subsequently, it still looked like the deferred antipattern, and after a little while of thinking and Googling, I reduced it to this:

function save() {
    return confirm().then(function(response) {
        return commit();
    }, function(rejection) {
        return $q.reject(rejection);
    });
};


Now, that looks pretty good to me, but I'm not sure if it's as good as it can be. All three versions above are functional, but is there perhaps a fourth iteration that would reduce it even further, or is this the simplest form for this depth of promises?

I've created a fiddle here for anyone who may want to see it in action.
You can also leave out reject. Your code would look like:

function save() {
    return confirm().then(function(response) {
        return commit();
    });
};


The promise returned by then() will automatically be rejected if the promise returned by confirm() is rejected.

Combining with @ShaunH's answer you would be left with

function save() {
    return confirm().then(commit);
};