14

I am using node-postgres to query my database and would like to know how to use async/await and handle errors correctly

An example of my use is here with a very simple query

const { Pool } = require('pg');

let config;
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') {
  config = { connectionString: process.env.DATABASE_URL, ssl: true };
} else {
  config = {
    host: 'localhost',
    user: 'myuser',
    database: 'mydatabase',
  };
}

const pool = new Pool(config);

async function getAllUsers() {
  let response;
  try {
    response = await pool.query('select * FROM users');
  } catch (error) {
    throw error;
  }
  return response.rows;
}

Then in my routes.js I have

app.get('/all_users', async (req, res) => {
  const users = await queries.getAllUsers();
  console.log(users); // returns all users fine
});

This is my understanding so far, but i don't think I am approaching this correctly as when it comes to errors my app will freeze and throw UnhandledPromiseRejectionWarning. So if I provide an incorrect table for example

async function getAllUsers() {
  let response;
  try {
    response = await pool.query('select * FROM notable');
  } catch (error) {
    throw error;
  }
  return response.rows;
}

UnhandledPromiseRejectionWarning: error: relation "notable" does not exist

The app will crash after 30 seconds and I have not handled this error gracefully. What am I missing?

1
  • For handling errors you might want to look at await-to-js which provides cleaner syntax for error handling when working with promises Commented Sep 6, 2019 at 7:31

1 Answer 1

21

When an async function or Promise throws an uncaught error, or when the catcher also throws, such as with your

throw error;

this means that the caller of the function will be faced with a rejected Promise to deal with. If you're using await in the caller, then you'll also have to use try/catch in the caller in order to catch the errors properly:

app.get('/all_users', async (req, res) => {
  try {
    const users = await queries.getAllUsers();
    console.log(users);
  } catch(e) {
    // handle errors
  }
});

Another way to resolve the error without having to use try/catch in the consumer would be not to throw the error in your catch:

async function getAllUsers() {
  let response;
  try {
    response = await pool.query('select * FROM users');
    return response.rows;
  } catch (error) {
    // handle error
    // do not throw anything
  }
}

but this will make it harder for the consumer to know when there was an error.

In this particular case, the async/await/try/catch constructions add a lot of syntax noise without much benefit IMO - for the moment, you might consider using plain Promises instead:

const getAllUsers = () => pool.query('select * FROM users')
  .then(response => response.rows);

// and:
app.get('/all_users', (req, res) => {
  queries.getAllUsers()
    .then((users) => {
      console.log(users);
    })
    .catch((err) => {
      // handle errors
    });
});

async and await shines when you have a few .thens that you'd like to look flatter in your code. If there's only one .then, IMO there's not much benefit to transforming it into async/await syntax. Of course, it's up to you.

Sign up to request clarification or add additional context in comments.

3 Comments

In addition to the above, a common option is to use a server package or middleware that automatically catches unhanded errors and just turns them into HTTP 500s.
Thanks for your answer, maybe I am using async/await unnecessarily, valid point raised. Also thank you for clearing up that i should be handling the error from the caller side to (simple thing i missed there)
It's common to have a single query executor function which has the try catch and call that elsewhere, so you don't have to repeat it everywhere. See node-postgres.com/guides/project-structure

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.