
Member-only story
Node.js, MySQL and async/await
Writing asynchronous applications in Node.js can be hard to learn, but except for some really simple cases, it cannot be avoided. Accessing a database is an example of an operation which is asynchronous by nature. It means that you have to wait for the results of a query, but while waiting, your program will continue to execute. For example, it can do some calculations or send another query to the database in parallel.
In a traditional, synchronous programming language like PHP, you could simply write:
$result = $connection->query( 'SELECT * FROM users WHERE id = 1' );
In JavaScript, you have three options to write asynchronous code:
- Using callbacks:
db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
2. Using promises:
db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
3. Using the await
keyword:
const rows = await db.query( 'SELECT * FROM users WHERE id = 1' );
At first, the difference seems purely cosmetic. It’s just different syntax for achieving the same thing. The differences become more obvious when you try to do something more complex.
Limitations of callbacks and promises
In my earlier article, Node.js, MySQL and promises, I gave an example of executing a few queries, one after another, and subsequently closing the connection.
When using plain callbacks, this requires nesting the callback functions and checking the error result in each function, which leads to a “callback hell”.
With promises, the code becomes more elegant, because you can chain multiple then()
handlers and use one catch()
handler for all errors. However, extracting the query results and closing the connection regardless of a success or error still requires some effort.
The situation becomes even worse when you have to introduce loops and conditions into an asynchronous code. Imagine the following hypothetical synchronous pseudocode:
const users = db.query( 'SELECT * FROM users WHERE id = 1' );
for (…