Как я могу обернуть каждый экспресс-запрос 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
под капотом.