Jiew Meng
Jiew Meng

Reputation: 88207

Handling Errors in A Chain of Promises

I am using Q.js as a promises library. Previously, theres code like:

function X() {
    return Q.Promise(function(resolve, reject) {
        Users.find()
            .then(function(user) {
                Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ])
                    .spread(function(profile, something) {
                        // do stuff

                        resolve();
                    })
                    .catch(function(err) {
                        // handle error for Q.all()

                        reject();
                    })
            })
            .catch(function(err) {
                // handle error for User.find()

                reject();
            });
    });
}

But now I learnt that I can remove the nesting with something like:

function X() {
    return Q.Promise(function(resolve, reject) {
        return Users.find()
            .then(function(user) {
                return Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ]);
            })
            .spread(function(profile, something) {
                // do stuff

                resolve();
            })
            .catch(function(err) {
                // now how do I differenciate between 
                // the errors from Users.find() and Q.all()?

                reject();
            });
    });
}

The "problem" I have with the bottom (flattened) version is how do I differenciate the errors from Users.find() and Q.all()? Or in general possibly many other errors in the long then chain?

Currently I might use something like

function(err) {
    if (err.errors && err.statusCode) {
        // do something
    } else if (err.message) {
        // do something
    }
}

But this is not really "nice" code isit? There must be a better way?

Upvotes: 2

Views: 538

Answers (1)

thefourtheye
thefourtheye

Reputation: 239473

You can use multiple catch blocks, like this

function X() {
    return Q.Promise(function(resolve, reject) {
        return Users.find()
            .catch(function(err) {
                 // Handle user finding error
                 throw new Error("Problem in finding users");
            })
            .then(function(user) {
                return Q.all([
                    getUserProfileInfo(user),
                    getUserSomethingElse(user)
                ]);
            })
            .spread(function(profile, something) {
                // do stuff

                resolve();
            })
            .catch(function(err) {
                reject();
            });
    });
}

Now, if there is a problem in finding the user, the first catch block will be executed and since you are throwing an Error from that, it will reach the next catch block in the chain. If there is no error in the Users.find then control will directly go to the then block.

Upvotes: 2

Related Questions