In order to make this question as useful to as many people as possible, I will exclude my specific implementation details beyond that fact that I am using the Bluebird promise library with Node + Express below.
So, let's say that I have the following chain (where P returns a promise, and res is the Express HTTP response object):
P().then(function(){
    // do nothing if all went well (for now)
    // we only care if there is an error
}).catch(function(error){
    res.status(500).send("An error occurred");
}).then(function(){
    return P();
}).then(function(pVal1){
    return [pVal1, P()];
}) // TODO: catch an error from P() here and log pVal1
.spread(function(pVal1, pVal2){
    if(pVal1 === pVal2) {
        console.log("Success!");
    } else {
        console.log("Failure");
    }
});
Where I have placed the TODO comment above is where I would like to catch an error that might occur from my call to P. If I do catch an error, I would like to log pVal1 and then send a 500 error, as is done in the first catch. However, I am not sure if this is possible with how I am structuring my chain.
I believe that I need to do some "branching," but I do not think that I understand this concept well enough to stop the asynchronous nature of JavaScript from getting the best of me! As such, any help is thoroughly appreciated.
The catch() method returns a Promise and deals with rejected cases only. It behaves the same as calling Promise.
If an error condition arises inside a promise, you “reject” the promise by calling the reject() function with an error. To handle a promise rejection, you pass a callback to the catch() function. This is a simple example, so catching the rejection is trivial.
Errors inside the Promises If you throw an error inside the promise, the catch() method will catch it, not the try/catch. In this example, if any error in the promise1, promise2, or promise4, the catch() method will handle it.
The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result. Here is an example with a promise that resolves in 2 seconds.
Don't forget to catch errors in the end of the chain. That's also the place to send the response.
Catching errors in the middle of a chain is for intermittent error handling; the chain continues to run, so don't send a response just yet.
Here is something to try it out:
// example middleware
function handle(req, res, next) {
    log("----------------");
    return async("p1", "foo").then(function (pVal1) {
        return pVal1;
    }).then(function (pVal1) {
        var p2a = async("p2a", "bar"),
            p2b = async("p2a", "bar").catch(function (error) {
                log("Logging: " + error + " (pVal1 " + pVal1 + ")");
            });
        return [p2a, p2b];
    }).spread(function (pVal1, pVal2) {
        if (pVal1 === pVal2) {
            res.send("Success!");
        } else {
            res.send("Failure");
        }
    }).catch(function (error) {
        res.status(500).send("An error occurred");
        log("Logging: " + error);
    });
}
// ---------------------------------------------------------------------
// mockup response object
var res = {
    status: function (code) {
        log("Sending status: " + code);
        return this;
    },
    send: function () {
        log("Sending response: " + [].join.call(arguments, " "));
        return this;
    }
};
// mockup promise generator
function async(name, value) {
    return new P(function (resolve, reject) {
        if ( confirm("let " + name + " succeed?") ) {
            log(name + " succeeds...");
            resolve(value);
        } else {
            log(name + " fails...");
            reject(name + " has failed");
        }
    });
}
function log() {
     var msg = document.createElement("DIV");
     msg.textContent = [].join.call(arguments, " ");
     document.getElementById("log").appendChild(msg)
     document.body.scrollTop = document.body.scrollHeight;
}
button {
    position: fixed;
    top: 5px;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.33/bluebird.min.js"></script>
<button onclick="handle(null, res, null)">Go</button>
<div id="log"></div>
This is possible if you use the explicit Promise.all instead of returning an array into .spread.
}).then(function(pVal1){
    // this becomes a `Promise.all` - the aggregation is explicit
    var all = Promise.all([pVal1, P()]);
    all.catch(function(e){  // "branching", we both return and `catch` the promise
        console.log("Error, pVal1 is", pVal1);
    });
    return all; // return it
}).spread(function(pVal1, pVal2){
       // ....
});
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With