Reputation: 25
I've been using node for a couple of months. For error handling in asynchronous code, I've been following the best practice I'm aware of, which is to handle errors via the callback error argument, and to let most exceptions bubble up and crash the app, since there isn't really a way to cleanly recover.
I'm working now on a project with a developer who uses Q, and he's calling some of my callback based functions with a wrapper using Q.nfbind. However, this is giving me headaches with error handling. For example, suppose I have a function that can callback with an error:
function doSomething(x, callback) {
dbpool.acquire(function(err, conn) {
if (err) return callback(err);
conn.query('INSERT INTO some_table (x) VALUES (?)', [x],
function(err, result) {
dbpool.release(conn);
if (err) return callback(err);
callback(null, result.insertId);
});
}
var qDoSomething = Q.nfbind(doSomething);
With Q I can then call qDoSomething and handle the error ok:
qDoSomething('abc')
.fail(function(err) {
...
});
Now suppose I was working too late one night, and checked in code like this inside my doSomething() function just before the query:
var foo;
foo.doAnotherThing();
In my pre-Q world this would be bad. An exception would be thrown, which would cause the app to crash, and it would restart via forever. However, once the app restarted, it would at least be functional until this code path was hit again. However, with Q, this exception is now caught and handled by the fail handler. This handler can't repair the damage, since it knows nothing about the connection pool. Now, every time this code path is hit, a connection is leaked from the pool and eventually the app is bricked. The impact of this bug just went from bad to terrible.
I don't know of a way with Q to differentiate between errors that were originally thrown and those that originated via a callback error. It seems like I'm stuck handling everything or nothing. Can anyone suggest a way to get back from terrible to bad?
Upvotes: 2
Views: 1434
Reputation: 203304
How about subclassing Error
to wrap those err
's in?
var MyError = function() {
Error.apply(this, arguments);
};
var generateError = function(callback) {
callback(new MyError('some reason'));
};
var doSomething = q.nfbind(generateError);
doSomething()
.fail(function(e) {
console.log('Was this a MyError instance?', e instanceof MyError);
});
Upvotes: 1