Henry
Henry

Reputation: 530

Using express, await, catch and next to stop function execution on error

I'm writing an express JS app using this style for routing:

router.post('/account/create', async function(req, res, next) {
    var account = await db.query(`query to see if account exists`).catch(next);
    if (account) {
        res.send('Email is unavailable.');
    } else {
        // Create account
    }
});

If the query returns successful but with no rows, the route executes perfectly. account is empty and so the if statement works and we create an account.

However if there was an issue with the db query, the catch statement is called and account is undefined, so the function continues to attempt to create a new account, even though next has been called which logs the error and sends a 500.

In an effort to continue with the ease of this async/await simple coding style, is there a way to easily stop function execution (or another solution) to prevent the subsequent code from executing without going back to callbacks?

Upvotes: 0

Views: 1003

Answers (2)

Henry
Henry

Reputation: 530

I've decided to use the solution here which is to wrap my route handlers in a function that catches errors for the entire route handler and calls next. Then if I need to handle an error specifically I can use try-catch. So 90% of cases use the default next error handler, the other 10 just use try-catch.

Keeps everything clean and super convenient, and you don't ever have to use .catch() on await calls.

Upvotes: -1

Lee Brindley
Lee Brindley

Reputation: 6482

Something like below should do the job?

It utilises try / catch, coupled with async/await, this way there are no callbacks.

router.post('/account/create', async function(req, res, next) {

  var account; 
  try {
      account = await db.query(`query to see if account exists`);
  } catch (e) {
    return res.status(500).send("Error checking if account exists.");
  }

  // If the account exists, return early
  if (account) {
    return res.status(500).send("Account already exists.");
  }

  // Account doesn't exist, so let's create the account!

  try {
    // Here you could create your new user account, and save it in the database, the catch would catch any DB error.

   // await db.query......

  } catch (e) {

    // Something went wrong creating the account, oops! Return.
    return res.status(500).send("Error creating account");
  }

  // The account would have been created at this point.
  return res.status(200).send("Account created!");
});

Using promises, without async/await.

router.post('/account/create', async function(req, res, next) {

  db.query(`query to see if account exists`)
    .then((account) => {

      // If the account exists, return early
      if (account) {
        return res.status(500).send("Account already exists.");
      }

      // Now create account
      db.query(`query to create account`)
        .then((result) => {

          // Account created fine, return.
          return res.status(200).send("Account created!");
        })
        .catch((err) => {

          // Error creating account, return.
          return res.status(500).send("Error creating account");
        });

    })
    .catch((err) => {
      return res.status(500).send("Error checking if account exists.");
    })

});

Upvotes: 2

Related Questions