node.js await/async trap when chaining

TechupBusiness
2 min readSep 23, 2018

This article is written for developers and about JavaScript basics, when working with asynchronous methods and await .

Never try to access a property or method of your awaited result (without brackets). It will result in (seemingly) very strange behavior at another place(s) of your code.

“orange excavator” by Luke Besley on Unsplash (Partner of OST.com)

Recently we ran into the problem, that suddenly at a specific line of the code, the debugger just seemed to jump out of the function to a parent function without reaching catch or finally or any other exception handling. Like it would swallow any error. It happened always at the following line of code:

client = await this._pool.connect()

It just ignored every try to catch and tackle the problem:

process.on('unhandledRejection', (err) => {
console.error(err)
})
...this._pool.on('error', (err, client) => {
let { logger } = self.loadModules()
logger.logCritical(err.message, 'Database error', err)
})
...this._pool.connect().then(...).catch(...)...try {
client = await this._pool.connect()
} catch(ex) {
logger.logCritical(ex)
} finally {
logger.logInfo('Why is this not reached?')
}

Even though this method was called multiple times successfully, suddenly at one call it stopped working and seemed to push the debugger back in the stack to a parent method, a few levels up. Was there something really strange going on with the development environment, maybe a memory issue or triggered node.js bug by the database connector?

After a while some clouds started to dissolve, it was not throwing an error or breaking the interpreter execution, it simply didn’t wait for the promise! Instead this method was suddenly executing asynchronous without waiting, ignoring any await in front of it. It only happened for a specific method call chain, which looked like this:

getPricePoint(...)
|-- getCandles(...)
|-- runSelectQuery(...)
|-- query(...)

Even though the await command was used properly, there was something different to “normal” for one call in getCandles:

return await this.runSelectQuery(table, where, {
start: 'ASC'
}, Limit).rows

The magical .rows … After removing this piece of code, suddenly the code execution was working again like expected, no “magical” removal of the await by the interpreter any longer. The await was waiting, everything worked again like it should:

client = await this._pool.connect() // waiting \o/

So if your await is not waiting for a promise-returning method in node.js, simply check if you maybe made a mistake in the parent stack chain. Like calling a method or reading a property of the returned await result “directly”. Unfortunately this doesn’t result in an error, even though the property .rows is obviously not a function and definitely not async, which could be awaited for by the interpreter. Means node.js will silently run your awaited method without any notification asynchronously, without waiting.

Just to make it complete: Of course you CAN chain, but then do it smart and use brackets:

return (await this.runSelectQuery(table, where, {
start: 'ASC'
}, Limit)).rows

--

--