Unable to handle exception with node.js domains using express

独自空忆成欢 提交于 2019-11-29 01:29:27

The problem is that the exception happens during Connect's routing, which has both a try/catch block around its execution, as well as a default error handler which prints out stack trace details when running in a non-production mode. Since the exception is handled inside of Express, it never reaches your outer layer for the domains to handle.

How it differs from exception2 is that the handler function for the '/' route is executed directly by that Connect block, in the same stack as the original call that went through Express. The second exception occurs in a callback, after some I/O operation has returned, and therefore is executed by a stack originating from Node's event loop I/O handler, and so the try/catch of Express isn't available to snag that exception and save the app server. In fact, if you comment out all the domain stuff, and trip exception2 it crashes Node.

Since only unhandled exceptions are routed to the domain mechanism, and since exception1 has a try/catch visible in it's call stack above it, the exception is handled, and not forwarded to the domain.

Connect-domain allows you to catch all errors for connect modules including express.

Connect-domain https://github.com/baryshev/connect-domain

The example for express3: http://masashi-k.blogspot.com/2012/12/express3-global-error-handling-domain.html

@user1007983

No, in production, the try/catch handling still exists in Connect/Express. The way to solve it is to add your own try/catch block in the "root" which you can then use to emit an "error" event to the domain before connect sends the error response.

try {
    // .. code here ..
} catch (err) {
    domain.emit('error', err);
}

Another way to get around it is to just disconnect from the handler, like wrapping your code in a setImmediate block

I've tried try/catch blocks (which may not work the way you think with async code). I've tried node domains in several different ways. But I was unable to handle an exception thrown in a 3rd party lib (sequelize). Why did I get the exception? Well, it was because the SQL that was generated was not well formed. (My fault).

Anywho, the solution that worked best for me and my (small) project was to use forever. Let the exceptions happen, but fire up node again if they do. I doubt it is the most elegant solution, but it works for me and my small project.

With a larger project, domains combined with the clustering API might be a good choice.

Winston is another choice. It might be cool to combine forever with winston so that if you DO get an exception, you can have winston email you, so you can fix the code. Meanwhile, forever will happily restart the app for you.

I came across this problem while testing my domain-based error handling.

I went with the approach suggested here by Issac, with a couple of minor changes: use 'domain.active' to get the currently active domain and emit the error event on that, and I used a wrapper function to avoid having to modify all of my handler functions:

domainWrapper = function(func) {
    return function(req, res) {
        try {
            return func(req, res);
        } catch (err) {
            domain.active.emit('error', err);
        }
    }
}

Then changed this sort of thing:

app.get('/jobs', handlerFunc);

to this:

app.get('/jobs', domainWrapper(handlerFunc));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!