I've read several examples for using mysql in node.js and I have questions about the error handling.
Most examples do error handling like this (perhaps for brevity):
app.get('/countries', function(req, res) {
pool.createConnection(function(err, connection) {
if (err) { throw err; }
connection.query(sql, function(err, results) {
if (err) { throw err; }
connection.release();
// do something with results
});
});
});
This causes the server to crash every time there's an sql error. I'd like to avoid that and keep the server running.
My code is like this:
app.get('/countries', function(req, res) {
pool.createConnection(function(err, connection) {
if (err) {
console.log(err);
res.send({ success: false, message: 'database error', error: err });
return;
}
connection.on('error', function(err) {
console.log(err);
res.send({ success: false, message: 'database error', error: err });
return;
});
connection.query(sql, function(err, results) {
if (err) {
console.log(err);
res.send({ success: false, message: 'query error', error: err });
return;
}
connection.release();
// do something with results
});
});
});
I'm not sure if this is the best way to handle it. I'm also wondering if there should be a connection.release()
in the query's err
block. Otherwise the connections might stay open and build up over time.
I'm used to Java's try...catch...finally
or try-with-resources
where I can "cleanly" catch any errors and close all my resources at the end. Is there a way to propagate the errors up and handle them all in one place?
In order to handle specific error handling cases that have returned from the sql connection you can look at the the 'error' object returned from the callback.
so..
the console.log statement in the for loop above will output something like:
object
using these keys you can pass off the values to a handler
I think you can do something like this. No matter how, the connection will be released once it is done querying and the server will not crash because of the error.
This can be an alternative solution which is much simpler.
I've decided to handle it using es2017 syntax and Babel to transpile down to es2016, which Node 7 supports.
Newer versions of Node.js support this syntax without transpiling.
Here is an example:
Using
async
/await
along with thistry { try { } finally { } } catch { } pattern
makes for clean error handling, where you can collect and deal with all your errors in one place. The finally block closes the database connection no matter what.You just have to make sure you're dealing with promises all the way through. For database access, I use the
promise-mysql
module instead of plainmysql
module. For everything else, I use thebluebird
module andpromisifyAll()
.I also have custom Exception classes that I can throw under certain circumstances and then detect those in the catch block. Depending on which exceptions can get thrown in the try block, my catch block might look something like this:
pool.js:
errors.js:
Another elegant solution is to use
async.series
, and its way of managing errorsThis is a function to return available pool upon successful MySQL connection. So before I proceed with any query, I'll await this function to check whether connection is OK. This will not crash the server even if there's no connection to MySQL.
MySQL package used: https://www.npmjs.com/package/mysql
Native Promise async/await ES2017