Javascript 快速:调用错误处理程序中的下一个

Javascript 快速:调用错误处理程序中的下一个,javascript,node.js,express,error-handling,Javascript,Node.js,Express,Error Handling,我正在实现一个node+express js应用程序,在错误处理程序中调用next函数时遇到问题 我在每个控制器中都有一个render中间件,由next调用,我希望我的错误处理程序也一样。我在controler中所做的是将一些viewProperties放入req中,然后调用下一个中间件来检索这些属性并呈现相应的响应 function render(req, res, next) { // viewName, title, args var properties = req.viewP

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

我在每个控制器中都有一个
render
中间件,由
next
调用,我希望我的错误处理程序也一样。我在controler中所做的是将一些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()
客户端的请求只是挂起的,从未收到。 因此,我尝试创建与错误处理程序相同的中间件:相同的函数,但arity为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
方法作为一个简单的函数(不是声明的中间件)复制到我的错误模块中。然后调用它,而不是
重定向错误
错误处理程序中的
next
。那也有同样的行为。调用了该函数,但客户端未接收任何内容

鉴于

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

我真的有点不明白。这可能是一个更深层次的问题,我还没有注意到。。。 黑暗中的谜语

编辑N2

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

总之,一个好的做法是在调用next时始终使用
return


感谢LaggingReflect,这让我继续了下去。

如果存在错误(抛出或通过
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
});

如果存在错误(抛出或通过
next
)传递),则只调用能够处理错误的下一个中间件(使用
(err,req,res,next)
的arity定义的中间件)

相反,如果不存在错误,则不会调用错误处理程序中间件
(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
});

redirectError
是最后一个中间件吗?如果是这样的话,就没有什么要转到下一个
,所以不知道为什么要调用它。最后一个中间件是
render
。它是在重定向错误后设置的,因此确实有一个下一步要去。我甚至用日志对它进行了测试,
渲染
中间件正确地打印它
重定向错误
是最后一个中间件吗?如果是这样的话,就没有什么要转到下一个
,所以不知道为什么要调用它。最后一个中间件是
render
。它是在重定向错误后设置的,因此确实有一个下一步要去。我甚至用日志和
渲染
中间件对它进行了测试,正确地打印出来。谢谢你的回答,但我知道这一点。实际上,正如我在前面的评论中所说,我将日志放在
render
方法中,它们都在经过错误处理程序后打印到最后一行。这意味着调用了
res.render(…)
,但请求在客户端处于挂起状态,我从未得到任何响应。我不明白为什么…我明白了,我本想发表一个评论,但时间太长了。无论如何。您可以
呈现
日志(打印在客户端?),那么请求如何仍然挂起?我忘了说它只是服务器端日志。我在render方法中输入了一些
consol.log()
,在传入
redirectError
后,它们被很好地打印在我的服务器控制台上。这意味着对
next()
的调用运行良好,
res.render(properties.name,properties)。但我从来没有收到过客户方面的任何东西。。。是否有我不适用的回复格式要求,或其他要求?对我来说,这真是一种奇怪的行为。我明白了。什么是
properties.name,properties
?另外,请尝试在渲染后放置另一个错误处理程序中间件,以查看是否引发了任何错误。如果你可以看一下的话<代码>属性
是一个包含视图模型信息的对象(我使用jade)。它取自
req
。我把它放在整个中间件流程的
req
中。谢谢你的回答,但我知道。实际上,正如我在前面的评论中所说,我将日志放在
render
方法中,它们都在经过错误处理程序后打印到最后一行。这意味着调用了
res.render(…)
,但请求在客户端处于挂起状态,我从未得到任何响应。我不明白为什么…我明白了,我本想发表一个评论,但时间太长了。无论如何。您可以
呈现
日志(打印在客户端?),那么请求怎么还挂起?我忘了