【问题标题】:Express : Call to next in error handlerExpress : 在错误处理程序中调用下一个
【发布时间】:2015-01-13 03:14:52
【问题描述】:

我正在实现一个 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被调用了两次,这是一种非常糟糕的行为......

作为结论,一个好的做法是在调用 next 时始终使用return

感谢 laggingreflex 让我继续前进。

【问题讨论】:

  • redirectError 是最后一个中间件吗?如果是这样,就没有什么可以转到next 了,所以不知道你为什么要打电话。
  • 最后一个中间件是render。它是在redirectError 之后设置的,所以确实有下一个可以去。我什至用日志对其进行了测试,render 中间件正确打印了它

标签: javascript node.js express error-handling


【解决方案1】:

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

【讨论】:

  • 感谢您的回答,但我知道。实际上,正如我在之前的评论中所说,我将日志放在render 方法中,它们在通过错误处理程序后都打印到最后一行。这意味着 res.render(...) 被调用,但请求只是在客户端挂起,我从来没有得到任何回复。我不明白为什么......
  • 我明白了,我宁愿发表评论,但它太长了。无论如何。您可以render 日志(打印在客户端?)那么请求如何仍然未决?
  • 我忘了说它只是服务器端日志。在渲染方法中输入了一些consol.log(),在传入redirectError 后,它们很好地打印在了我的服务器控制台上。这意味着对next() 的调用运行良好,实际上调用了res.render(properties.name, properties);。但是我从来没有在客户端收到任何东西......是否有任何我不会申请的响应格式要求,或任何东西?对我来说,这是一种非常奇怪的行为。
  • 我明白了。 properties.name, properties 是什么?还可以尝试在渲染后放置另一个错误处理程序中间件以查看是否抛出任何错误。
  • 我刚刚添加了一个观察结果,作为对我的问题的编辑。如果你可以看看。 properties 是一个包含视图模型信息的对象(我使用玉)。它取自req。我把它放在req 中贯穿整个中间件流程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 2020-09-14
相关资源
最近更新 更多