【问题标题】:Using Mongoose pre save hook result in: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client使用 Mongoose 预保存挂钩会导致:错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端后无法设置标头
【发布时间】:2020-02-25 14:59:39
【问题描述】:

如果架构中不满足某个条件,我正在尝试挂接到 Mongoose 中的保存功能,以向 REST API 的客户端返回错误。我不能为此使用验证器,因为限制是在架构的多个字段上计算的。

我正在尝试添加以下样式的钩子:

mySchema.pre('save', function (next) {
  if(condition_is_not_met) {
    const err = new Error('Condition was not met');
    next(err);
  }
  next();
});

当我尝试调用端点尝试插入违反挂钩中检查的条件的对象时,这会引发错误:

错误 [ERR_HTTP_HEADERS_SENT]:发送后无法设置标头 给客户

我猜这是因为在路由上继续执行,写入标头以将其发送到客户端。

router.post('/mySchema', returnType, (req, res) => {
  const s = new mySchema(req.body);
  s.save((err) => {
    if (err) {
      const msg = { message: 'Could not add', error: err }; // This is returned to the caller
      res.status(500);
      res.send(msg);
    }
    res.status(200);
    res.send(s);
  });
});

我该如何解决这个问题?我一直在搜索很多,但到目前为止我发现的主题并不能帮助我解决我的问题。他们只是帮助我找出原因,却没有提供可行的解决方案。

【问题讨论】:

  • 您是否尝试为状态 200 放置一个 else 分支?
  • 我的意思是即使您发送的对象无效,执行仍然会成功响应,因此响应 2 次..
  • @Teebo 刚刚尝试过,但这也不能解决问题。如果我省略了钩子,则实际上不会引发错误。只需添加钩子,就会引入错误。它一定与某些不同步的东西有关,但我无法确定到底是什么。
  • @Teebo 我确实解决了它是不正确的。当我覆盖钩子中设置的错误时,我被抛弃了。需要解决这个问题以保证您对问题的解决方案有效。如果您将来为面临相同问题的其他人发布您的解决方案,我可以在弄清楚如何防止覆盖挂钩设置的错误后将其标记为解决方案。
  • 在此处添加返回:res.status(500);返回 res.send(msg);

标签: express mongoose mongoose-schema


【解决方案1】:

您是否尝试为成功响应创建一个 else 分支?因为即使对象无效,仍然会执行成功响应。像下面这样试试

router.post("/mySchema", returnType, (req, res) => {
  const s = new mySchema(req.body);
  s.save(err => {
    if (err) {
      const msg = { message: "Could not add", error: err };
      res.status(500);
      res.send(msg);
    } else {
      res.status(200);
      res.send(s);
    }
  });
});

请原谅我的代码格式,我是AFK

【讨论】:

  • 你被赦免了。这样做解决了问题,但需要将错误设置更改为: const msg = { message: (err.message) ? err.message : '无法添加', 错误: err };
  • 别担心,我格式化了。我们也可以像这样使用一行: res.status(500).send(msg);缩短代码。
  • @Ruud,我很高兴它为解决问题提供了一些启示!
  • @SuleymanSah 我知道我可以链接这些方法,但我需要确保其他人将来可以轻松地跟随执行。将每个动作分成单独的一行可以使代码对某些人来说更具可读性。
  • 我很好奇,错误仍然在节点控制台中抛出 500 状态,但是这样我可以向客户端返回 400 状态,这是相当正确的还是有另一种方法可以做到这一点?
猜你喜欢
  • 1970-01-01
  • 2020-05-26
  • 2018-09-19
  • 2020-09-22
  • 2023-01-19
  • 2021-02-26
  • 2021-08-20
  • 2019-09-28
相关资源
最近更新 更多