Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
866 views
in Technique[技术] by (71.8m points)

javascript - How can I wrap every express js request in a domain or trycatch

Is it possible to wrap every request coming through express.js in a domain or trycatch see trycatch info here?

I am trying to create a 'catch all' of sorts (the express error handler middleware does not catch async calls) to be sure any errors I miss are handled with a 500 being sent to the user.

If you have an asynchronous function call (eg. process.nextTick()), then it will be outside the scope of express' error handler, thus killing the process entirely. Thus, using the express error handler will not work in all cases.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Express already has error handler implementation. It inherit it from connect. To use it you need to add it as the last middleware point (last app.use(...) call). For example:

var express = require('express')
  , app = express();

app.use(app.router);
app.use(express.errorHandler());

// app.get(...), app.post(...), app.listen(...), etc.

If you want to handle all errors with simple 500 response code, you could replace express.errorHandler() with you own function. In that case your code will looks like:

var express = require('express')
  , app = express();

app.use(app.router);
app.use(function(err, req, res, next){
  if (!err) return next();
  res.send(500);
});

// app.get(...), app.post(...), app.listen(...), etc.

More information about that way could be found in express error example comments in code

UPDATE:

Of course you could use domain for each request. You could wrap each request separately or use wrapping for router to handle ALL exceptions. Code is following:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain');

//app.use(app.router);
app.use(function(req, res, next){
    var d = domain.create();
    d.on('error', function(er) {
        console.log('error, but oh well', er.message);
        res.send(500);
    });

    // explicitly add req and res
    d.add(req);
    d.add(res);

    d.run(function() {
        app.router(req, res, next);
    });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

!!BUT!! never use this in production. The reason of that is in nature how JS throw work. It will definitely be a cause of leaking in your application and make it even more unstable. You could use such error handling to implement custom algorithm of shutdown (for example to close already opened connection). More information about right use of domain could be found in documentation.

To monitor the leaking you could use the technique from this article.

UPDATE 2:

I just can't leave this not finished. trycatch code:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain')
    , trycatch = require('trycatch');

//app.use(app.router);
app.use(function(req, res, next){
   trycatch(function(){
           app.router(req, res, next);
       }, function(er){
           console.log(er.message);
           res.send(500);
       });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

I had review the source of trycatch and there was no any magic. It still be cause of leaks. trycatch has domain under the hood.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...