2

If I throw an Error, express renders it nicely using the connect errorHandler middleware.

exports.list = function(req, res){
  throw new Error('asdf');
  res.send("doesn't get here because Error is thrown synchronously");
};

And when I throw an Error within a promise it will be ignored (this makes sense to me).

exports.list = function(req, res){
  Q = require('q');
  Q.fcall(function(){
    throw new Error('asdf');
  });
  res.send("we get here because our exception was thrown async");
};

However, If I throw an Error within a promise and call "done" node crashes, because the exception isn't caught by the middleware.

exports.list = function(req, res){
  Q = require('q');
  Q.fcall(function(){
    throw new Error('asdf');
  }).done();
  res.send("This prints. done() must not be throwing.");
};

After running the above, node crashes with this output:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: asdf
    at /path/to/demo/routes/user.js:9:11

So my conclusion is that done() isn't throwing the exception, but causes an exception to be thrown elsewhere. Is that right? Is there a way to accomplish what I'm trying - where errors in the promise will be handled by the middleware?

FYI: This hack will catch the exception at the top level, but it's outside of the realm of middleware, so doesn't suite my needs (to nicely render the error).

//in app.js #configure
process.on('uncaughtException', function(error) {
  console.log('uncaught expection: ' + error);
})
mkirk
  • 3,965
  • 1
  • 26
  • 37

1 Answers1

2

Maybe you'll find connect-domain middleware useful for handling async errors. This middleware allows you to handle async errors like a regular errors.

var
    connect = require('connect'),
    connectDomain = require('connect-domain');

var app = connect()
    .use(connectDomain())
    .use(function(req, res){
        process.nextTick(function() {
            // This async error will be handled by connect-domain middleware
            throw new Error('Async error');
            res.end('Hello world!');
        });
    })
    .use(function(err, req, res, next) {
        res.end(err.message);
    });

app.listen(3131);
Vadim Baryshev
  • 25,689
  • 4
  • 56
  • 48
  • I think the hard part for me was just understanding that nodejs's event loop wasn't compatible with what I was taking for granted. The domain module seems to have been introduced to address this in some fashion. Thanks! http://nodejs.org/api/domain.html – mkirk Apr 07 '13 at 00:14