Express : 在错误处理程序中调用 next

Express : Call to next in error handler

我正在实现一个 node + express js 应用程序,但在错误处理程序中调用 next 函数时遇到问题。

我有一个 render 中间件,它在每个控制器中由 next 调用,我希望它与我的错误处理程序相同。我在控制器中所做的是将一些 viewProperties 放在 req 中,然后调用下一个中间件来检索这些属性并相应地呈现响应。

function render(req, res, next) {

  // viewName, title, args
  var properties = req.viewProperties || {};

  // We only handle a res.send(message)
  if (properties.body) {

    res.send(properties.body);
    return;
  }

  // We only handle a res.redirect(url)
  if (properties.redirect) {

    res.redirect(properties.redirect);
    return;
  }

  properties.lang = req.app.get('lang');
  properties.title = properties.title || 'Message_Me';
  properties.connected = req.session ? req.session.connected : false;
  properties.firstname = req.session.userFirstname || 'anonymous';

  res.render(properties.name, properties);
}

当我尝试将此中间件与我的错误处理程序一起使用时,使用 next() 请求只是在客户端挂起,从未收到。 因此,我尝试创建与错误处理程序相同的中间件:相同的函数,但元数为 4,然后在我的错误处理程序中调用 next(err)。这次在客户端收到响应,但没有正确呈现,它只显示堆栈跟踪。

我找到的唯一方法是将此函数复制到我的错误处理程序中并粘贴它,而不是调用 next。我不明白为什么它不能正常工作?

我的错误处理程序:

function redirectError(err, req, res, next) {

    // Ajax call running
    if (req.xhr) {

        req.viewProperties = { body : err.message };
        return next(err);
    }

    req.viewProperties = { name : 'layout/error', title : 'Erreur', message : err.message, err : err };

    // Here is the probleme
    next()
    // next(err);
}

编辑

我尝试了另一件事:我将 render 方法作为一个简单的函数(未声明的中间件)复制到我的错误模块中。然后在 redirectError 错误处理程序中调用它而不是 next。那做了同样的行为。该函数被调用,但客户端没有收到任何内容。

鉴于

如果我将 render 函数的内容复制到 redirectError 中,一切正常。

这里确实有我不明白的地方。这可能是我尚未注意到的更深层次的问题...... 黑暗中的谜语

编辑 N2

我发现我的错误了!!我在另一个中间件的 if 中忘记了 return 语句。这使得 next 被调用了两次,并且行为非常糟糕...

总而言之,一个好的做法是在下次调用时始终使用 return !

感谢 laggingreflex 让我坚持下去。

如果存在错误(抛出或通过 next),则仅调用下一个可以处理错误的中间件(定义为 (err,req,res,next) 的中间件)。

相反,如果 存在错误,则 调用错误处理程序中间件(err,req,res,next)

因此,在您的情况下,您的 redirectError 仅在 出现 存在 错误时被调用,并且您的 render 只有在没有的时候。

演示:

app.use(function(req, res, next) {
    throw(new Error('testing...'));
});
app.use(function(req, res, next) {
    // This won't be called
});
app.use(function(err, req, res, next) {
    // But This would
    next(); // not passing any Error this time
});

app.use(function(err, req, res, next) {
    // So now this won’t be called
});
app.use(function(req, res, next) {
    // But this would
});