martingo89 martingo89 - 6 months ago 23
Javascript Question

Promise chaining (angular javascript)

So I have a few functions that all make async calls to a service. I wan't them all to execute after the previous one is complete but only if the previous one didn't fail. It looks something like this:

var fn1 = function() {
var promise = aService.fn1();
var successCallback = function(response) {
return true;
};
var errorCallback = function() {
return false;
};
return promise.then(successCallback, errorCallback);
};
var fn2 = function() {
var promise = aService.fn2();
var successCallback = function(response) {
return true;
};
var errorCallback = function() {
return false;
};
return promise.then(successCallback, errorCallback);
};
var fn3 = function() {
var promise = aService.fn3();
var successCallback = function(response) {
return true;
};
var errorCallback = function() {
return false;
};
return promise.then(successCallback, errorCallback);
};

fn1().then(function(resp){
if (resp)
{
fn2().then(function(resp){
if (resp)
{
fn3().then(function(resp){
if (resp)
{
// all functions have been called in order were successful
}
});
}
});
}
});


The execution at the end looks pretty bad the more function are added to this chain. I wan't to know if there is another way I can structure this in way so it behaves the same but doesn't create a huge tree of chained async calls. If I can keep it on the same indentation that would be great. Thank you!

Answer

You have to modify the error callbacks to return $q.reject() instead of false, i.e.:

var fn1 = function() {
    var promise = aService.fn1();
    var successCallback = function(response) {
        // no return needed, unless the next stage
        // requires the results of this stage
    };
    var errorCallback = function() {
        return $q.reject();
    };
    return promise.then(successCallback, errorCallback);
};

The the chaining becomes:

fn1()
    .then(function() {
        return fn2();
    })
    .then(function() {
        return fn3();
    })
    .then(function() {
        // ALL SUCCEEDED HERE
    });

In fact you do not even have to write that painful code in f1, f2, f3, i.e. the following will also do the job:

aService.fn1()
    .then(function() {
        return aService.fn2();
    })
    .then(function() {
        return aService.fn3();
    })
    .then(function() {
        // ALL SUCCEEDED HERE
    });