Manuel Reis
Manuel Reis

Reputation: 574

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.

Upvotes: 2

Views: 1261

Answers (2)

Sherif eldeeb
Sherif eldeeb

Reputation: 2186

I tried this code, but it got resolved instead of rejected

new Promise(r=>r('b').then(()=>Promise.reject('x'))).catch(err=>console.log({error}))

result:

Promise {<fulfilled>: 'b'}

Upvotes: 0

Bergi
Bergi

Reputation: 664548

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);

Upvotes: 3

Related Questions