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?
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.
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.
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 .then
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With