如何正确处理Express中的错误?

YWC*_*llo 24 javascript middleware node.js express

我开始使用Express JS并遇到了一个问题.我似乎无法弄清楚处理错误的正确方法.

例如,我有一个Web服务API,它提供一个名为"event"的对象.当用户提交未找到的事件ID时,我想返回一个简单的"无法查找事件"字符串.以下是我目前正在构建代码的方式:

app.get('/event/:id', function(req, res, next) {
    if (req.params.id != 1) {
        next(new Error('cannot find event ' + req.params.id));
    }

    req.send('event found!');
});
Run Code Online (Sandbox Code Playgroud)

当我提交1以外的ID时,Node会崩溃并输出以下内容:

http.js:527
   throw new Error("Can't set headers after they are sent.");
         ^
Error: Can't set headers after they are sent.
    at ServerResponse.<anonymous> (http.js:527:11)
    at ServerResponse.setHeader (/usr/local/kayak/node_modules/express/node_modules/connect/lib/patch.js:62:20)
    at /usr/local/kayak/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js:72:19
    at [object Object].<anonymous> (fs.js:107:5)
    at [object Object].emit (events.js:61:17)
    at afterRead (fs.js:878:12)
    at wrapper (fs.js:245:17)
Run Code Online (Sandbox Code Playgroud)

从我通过使用node.js 调试器可以看出,在next()调用后继续执行代码块,这意味着req.send('event found!')尝试运行.我不希望这种情况发生.

我发现的唯一解决方法是简单地抛出一个new Error()而不是"next-ing"它,但这会导致生成默认的Express HTML错误页面.我想要比这更多的控制.

我花时间阅读Express文档的错误处理部分,但我无法理解它.

Cha*_*nce 35

您需要查看快速错误处理.从那里:

app.param('userId', function(req, res, next, id) {
    User.get(id, function(err, user) {
        if (err) return next(err);
        if (!user) return next(new Error('failed to find user'));
        req.user = user;
        next();
    });
});
Run Code Online (Sandbox Code Playgroud)

你缺少的甜点是 return next(...)


ale*_*lex 19

那是因为你做错了:你已经抛出一个错误(将由Express处理并为用户或类似的东西返回500 - 错误页面)但你也试图将自己的响应发送给客户端: res.send('event found!');

您应该在这里查看有关错误处理的Express指南:http://expressjs.com/guide/error-handling.html

我在你的例子中会做的是:

function NotFound(msg){
  this.name = 'NotFound';
  Error.call(this, msg);
  Error.captureStackTrace(this, arguments.callee);
} 

app.get('/event/:id', function(req, res, next){
  if (req.params.id != 1) {
    throw new NotFound('Cannot find event ' + req.params.id);
  } else {
    res.send('event found!');
  }
});

app.error(function(err, req, res, next){
    if (err instanceof NotFound) {
        res.render('404.ejs');
    } else {
        next(err);
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 但链接中的表达文档非常差.它甚至没有提到你应该如何正确地抛出错误,或者哪个版本的表达有效. (5认同)

evi*_*ery 10

您的代码中有几个问题:

  • 响应客户端时,需要使用响应对象(res而不是req).

  • 发送错误时next,您应该返回,因此该函数的其余部分不会运行.

修复这些错误后,这是您的代码:

app.get('/event/:id', function(req, res, next) {
    if (req.params.id != 1) {
        return next(new Error('cannot find event ' + req.params.id));
    }

    res.send('event found!'); // use res.send (NOT req.send)
}); 
Run Code Online (Sandbox Code Playgroud)