Manuel Reis Manuel Reis - 3 months ago 19
Node.js Question

Promises - catch inner throw

I have the following code, with some chained promises. I am trying to throw an error in an inner

then
that I expected to be caught by the outer
catch
, but it is not the current behavior:

User.getById(userId).then((user: any) => {
if (user.email != email) {
User.getByEmail(email).then((user: any) => {
throw new OperationError("exists"));
}).catch(StorageError, (err: any) => {
user.email = email;
return user.save();
});
} else {
return user.save();
}
}).then((user: any) => {
return {
ok: true,
user: user
};
}).catch(OperationError, (error: any) => {
return {
ok: false,
message: error.message
};
}).asCallback(reply);


How can I make the outer catch be targeted by the
throw
statement?

EDIT
Updated code as Vohuman suggested.

User.getById(userId).then((user: any) => {
finalUser = user;

if (user.email != email) {
return User.getByEmail(email);
}
else {
//I would like for this response [1] to be used in [2]
return Promise.resolve(user);
}
}).then((user: any) => {
throw new OperationError("Email already exists");
}).catch(StorageError, (error: any) => {

finalUser.email = email;
return finalUser.save();
}).then((user: any) => {
//[2] here is where I would like the else statement to come

sendEmail(user.email, subject, content);
return { ok: true, user: user };
}).catch(OperationError, (error: any) => {

return { ok: false, message: error.message };
}).asCallback(reply);


How can I now, resolve the user in the first else statement without having it caught in the following
then
?

The idea is to send an email confirmation if the email does not exist in the database OR if the email is the same as the requesting account (resend email confirmation). If the email already exists, I would like to abort execution.

Answer

Your approach is totally fine, you only forgot one little return. Without it, the inner promise won't be awaited and rejections won't trigger the outer catch.

User.getById(userId).then((user: any) => {
    if (user.email != email) {
        return User.getByEmail(email).then((user: any) => {
//      ^^^^^^
            throw new OperationError("exists"));
        }).catch(StorageError, (err: any) => {
            user.email = email;
            return user.save();
        });
    } else {
        return user.save();
    }
}).then((user: any) => {
    return {
        ok: true,
        user: user
    };
}).catch(OperationError, (error: any) => {
    return {
        ok: false,
        message: error.message
    };
}).asCallback(reply);