Как я могу обернуть каждый экспресс-запрос JS в домене или trycatch

Можно ли обернуть каждый запрос, поступающий через express.js в domain или же trycatch см. информацию по trycatch здесь?

Я пытаюсь создать своего рода "ловить все" (промежуточное ПО экспресс-обработчика ошибок не перехватывает асинхронные вызовы), чтобы быть уверенным, что любые ошибки, которые я пропускаю, обрабатываются с отправкой пользователю 500.

Если у вас есть асинхронный вызов функции (например, process.nextTick()), то он будет выходить за рамки экспресс-обработчика ошибок, тем самым полностью убивая процесс. Таким образом, использование экспресс-обработчика ошибок не будет работать во всех случаях.

1 ответ

Решение

У Express уже есть реализация обработчика ошибок. Он наследует это от подключения. Чтобы использовать его, вам нужно добавить его в качестве последней точки промежуточного программного обеспечения (последний вызов app.use(...)). Например:

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

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

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

Если вы хотите обработать все ошибки простым кодом ответа 500, вы можете заменить express.errorHandler() с вашей собственной функцией. В этом случае ваш код будет выглядеть так:

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.

Более подробную информацию об этом можно найти в комментариях к примеру с ошибками в коде.

ОБНОВЛЕНИЕ:

Конечно, вы можете использовать домен для каждого запроса. Вы можете обернуть каждый запрос отдельно или использовать обертку для маршрутизатора для обработки ВСЕХ исключений. Код следующий:

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');
});

!!НО!! никогда не используйте это в производстве. Причина этого в том, как JS бросает работу. Это определенно станет причиной утечки в вашем приложении и сделает его еще более нестабильным. Вы можете использовать такую ​​обработку ошибок для реализации собственного алгоритма выключения (например, чтобы закрыть уже открытое соединение). Более подробную информацию о правильном использовании домена можно найти в документации.

Для контроля утечки вы можете использовать технику из этой статьи.

ОБНОВЛЕНИЕ 2:

Я просто не могу оставить это не законченным. trycatch код:

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');
});

У меня был обзор источника trycatch и не было никакой магии. Это все еще будет причиной утечек. trycatch имеет domain под капотом.

Другие вопросы по тегам