0

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.

Fabio
  • 376
  • 6
  • 19
  • What's the error message you got? – Bergi Dec 16 '20 at 13:29
  • @Bergi if I send a new user the error code is "auth/user-not-found". If I send an already existing user it's a generic "Error: could not handle the request" – Fabio Dec 16 '20 at 13:38
  • The first makes sense - your `addClient` function always calls `updateUser`, see my answer. – Bergi Dec 16 '20 at 13:43

1 Answers1

1

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
        })
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I noticed that you didn't include a catch block for `admin.auth().updateUser`. Should I handle that or it's good as it is? – Fabio Dec 16 '20 at 14:10
  • @Fabio How would you handle it? Currently, with the promise being `return`ed, the error just bubbles up and will be caught in `addClients` and handled with `res.status(500).send(err)`. – Bergi Dec 16 '20 at 14:12