Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Async/Await with node-postgres

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

Could anyone point out what i am missing here please?

like image 322
Richlewis Avatar asked Dec 24 '18 08:12

Richlewis


People also ask

Can I use async await in Node?

Async functions are available natively in Node and are denoted by the async keyword in their declaration. They always return a promise, even if you don't explicitly write them to do so. Also, the await keyword is only available inside async functions at the moment – it cannot be used in the global scope.

Can we use PostgreSQL with Node js?

Using node-postgres , you will be able to write Node. js programs that can access and store data in a PostgreSQL database. In this tutorial, you'll use node-postgres to connect and query the PostgreSQL (Postgres in short) database. First, you'll create a database user and the database in Postgres.


1 Answers

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.

like image 163
CertainPerformance Avatar answered Sep 19 '22 13:09

CertainPerformance