Skip to content

Javascript: using catch block but not to handle an error

I’m in a situation where I have to use a catch block to execute some code but I don’t want to consider it an error. Basically, I want to update/create a user based on whether the user is already registered or not respectively. The admin sdk let me create a user, and if the user already exists it throws an error. So if I’m in the catch block I know that the user already exists and I want to update it.

function addClient(client) {
    return new Promise((resolve, reject) => {
        admin.auth().createUser({
            uid: client.id,
            email: client.email,
            emailVerified: true,
            password: client.password,
        }).then(record => {
            resolve(record);
            return null;
        }).catch(
            // the user already exist, I update it
            admin.auth().updateUser(client.id, {
                email: client.email
            }).then(record => {
                resolve(record);
                return null;
            }).catch(
                err => {
                    reject(err);
                }
            )
        );
    });
}

The problem is that when I call the function with an existing user, it is updated correctly but the HTTP response is an internal server error (I guess because it enters the catch block and it considers this as an error). The same is if I send a new user: it is created correctly but the HTTP response code is a 500. There is a way to avoid this behaviour?

This is the main function that calls the previous one for each user received and it’s responsible for sending the HTTP response:

exports.addClients = functions.https.onRequest((req, res) => {
    // fetch recevied list from payload
    var receivedClients = req.body.clients;

    var promises = [];

    receivedClients.forEach(client => {
        promises.push(addClient(client));
    })

    Promise.all(promises)
        .then(() => {
            res.sendStatus(200);
            return null;
        })
        .catch(err => {
            res.status(500).send(err);
        });
});

I guess that what I want to achieve is to have all the promises resolving.

Answer

You need to pass a callback to .catch, not a promise. Also avoid the Promise constructor antipattern!

function addClient(client) {
    return admin.auth().createUser({
        uid: client.id,
        email: client.email,
        emailVerified: true,
        password: client.password,
    }).catch(err => {
//           ^^^^^^^^
        // if (err.code != "UserExists") throw err;

        return admin.auth().updateUser(client.id, {
            email: client.email
        })
    });
}