vinoli vinoli - 2 months ago 13
AngularJS Question

Sequential promises

I need to get four response's promises, but to do this I first have to call every function in sequence, from the first to the last. You can see from my code that I call the next function in the promise callback from the last called function.

But the code doesn't look appropriate, so I need to know if there is some better way to do this.

Any suggestions?

$scope.createPayment = function() {
var dados = $scope.card;
// get first promise
PagamentoMP.createToken(dados)
.then(
function(result) {
dados.token = result;
// get second promise
PagamentoMP.guessPaymentMethod(dados)
.then(
function(result) {
dados.paymentMethod = result;
// get third promise
PagamentoMP.getIssuers(dados)
.then(
function(result) {
dados.issuer = result;
// get fourth promise
PagamentoMP.getInstallments(dados)
.then(
function(result) {
dados.installments = result;
},
// error for fourth promise
function(result) {
console.log("getInstallments PAGAMENTOMP -> Failed to get the name, result is " + result);
}
);
},
// error for third promise
function(result) {
console.log("getIssuers PAGAMENTOMP -> Failed to get the name, result is " + result);
});
},
// error for second promise
function(result) {
console.log("guessPaymentMethod PAGAMENTOMP -> Failed to get the name, result is " + result);
});
},
// error for first promise
function(result) {
console.log("createToken PAGAMENTOMP -> Failed to get the name, result is " + result);
});
};

Answer

Instead of doing this,

a().then(function(result) {
    b(result).then(function(result) {
        c(result).then(function(result) {
            console.log("done");
        });
    });
});

you can chain all the promises at the top level.

a()
    .then(function(result) {
        return b(result);
    })
    .then(function(result) {
        return c(result);
    })
    .then(function(result) {
        console.log("done");
    });

This same pattern can be used in your code.

To catch errors, add a .catch at the end of the chain if you want one error handler for all errors in the chain.

a()
    .then(function(result) {
        console.log("done");
    })
    .catch(function(err) {
        console.error(err);
    });

For separate error handlers at each step, you can do something like this:

a()
    .catch(function(err) {
        console.log("error in a");
        throw err;
    })
    .then(function(result) {
        return b()
            .catch(function(err) {
                console.log("error at b");
                throw err;
            });
    })
    .then(function(result) {
        return c()
            .catch(function(err) {
                console.log("error at c");
                throw;
            });
    });

Each error handler needs to call throw so that it does not continue down the chain when an error happens.