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

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

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

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


person bzuillsmith    schedule 30.10.2013    source источник


Ответы (1)


В Express уже есть реализация обработчика ошибок. Он наследуется от connect. Чтобы использовать его, вам нужно добавить его в качестве последней точки промежуточного программного обеспечения (последний вызов 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 throw. Это определенно станет причиной утечки в вашем приложении и сделает его еще более нестабильным. Вы можете использовать такую ​​обработку ошибок для реализации собственного алгоритма завершения работы (например, для закрытия уже открытого соединения). Дополнительную информацию о правильном использовании домена можно найти в документации.

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

ОБНОВЛЕНИЕ 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 под капотом.

person andbas    schedule 30.10.2013
comment
Извините, это не охватывает все случаи. Я отредактирую вопрос, чтобы упомянуть, что я уже рассмотрел это. Если у вас есть асинхронный вызов функции (например, process.nextTick()), то он выйдет за рамки экспресс-обработчика ошибок, что полностью убьет процесс. Есть такие вещи, как domains и модуль trycatch, которые смягчают эту проблему, но я не уверен, как обернуть экспресс-запрос в домен или попробовать. - person bzuillsmith; 31.10.2013
comment
Я обновил свой ответ. Конечно, можно, но я не думаю, что это хорошая идея. Возможно, вы захотите использовать настройку при завершении работы и что-то вроде forever, чтобы ваш скрипт работал непрерывно. - person andbas; 31.10.2013
comment
trycatch делает много шимминга в основных библиотеках, чтобы предотвратить утечки и другие проблемы. Спасибо за код. Не уверен, что смогу сделать то же самое с помощью trycatch, но, думаю, я перенесу это обсуждение в репозиторий trycatch. - person bzuillsmith; 02.11.2013
comment
Зуилл, чтобы помочь вам, я добавил пример trycatch, но, пожалуйста, помните, что trycatch — это не серебряная пуля, он по-прежнему использует домен и не может предотвратить утечки. - person andbas; 02.11.2013
comment
В Express 4: Ошибка: большая часть промежуточного программного обеспечения (например, errorHandler) больше не входит в состав Express и должна устанавливаться отдельно. - person Husky; 18.04.2015
comment
Можно ли этот код: d.run(function() { app.router(req, res, next); }); заменить на этот: d.run(next)? - person Eugene Mala; 16.05.2015
comment
app.router(req, res, next); устарело в Express 4.x - person Eugene Mala; 16.05.2015
comment
@andbas Целесообразно ли использовать домен? Официальные документы говорят, что он будет устаревшим. Каковы другие способы обработки ошибок в узле js? - person inertia; 03.06.2016