繁体   English   中英

Node/Express:为什么不能将 res 传递给帮助程序 function(例如用于验证)并避免 ERR_HTTP_HEADERS_SENT?

[英]Node/Express: Why can't you pass res to a helper function (e.g. for validation) and avoid ERR_HTTP_HEADERS_SENT?

我有一个使用 Node (v.18.2) 和 Express (v. 4.18) 构建的 web 应用程序。 用户可以发送 POST 请求,我会在他们到达时进行验证; 如果用户犯了错误,我会发回一条错误消息,以便用户知道出了什么问题。

在这样做时,我想添加一些辅助函数,因为这些检查会在许多端点中发生,并且我想保持我的代码干燥,例如用户是否发送了正确类型的输入,她的帐户中是否有足够的信用, 等等。

我的意图是将res function 传递给这些请求,以允许他们向用户发回响应。 但是,代码继续运行,遇到另一个res.json ,这当然会触发错误[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

这是我从代码库中提取的简化示例:

app.post("/demonstration", async (req, res) => {
  const user = req.body.user;
  // user = {id: 123, credits: 0}

  // Validation - Check if user has enough credits
  await checkCredits(user, res);

  res.json({ result: "success" });
  return;
});

function 定义为:

async function checkCredits(user, res) {
  const credits = user.credits;

  if (credits <= 0) {
    res.json({ result: "failure" });
    return;
  }
}

基于这篇文章的一个直接解决方案是让checkCredits返回 true/false,然后在主体的 if/else 语句中使用它来决定是发送成功还是失败响应,如下所示(有效):

app.post("/demonstration", async (req, res) => {
  const user = req.body.user;
  // user = {id: 123, credits: 0}

  // Validation - Check if user has enough credits
  const hasEnoughCredits = await checkCredits(user); // Returns true if user has enough credits

  if (!hasEnoughCredits) {
    res.json({ result: "failure" });
    return;
  }

  res.json({ result: "success" });
  return;
});

我只是不明白(A)为什么res不能被传递(在第一个例子中)和/或(B)为什么res.json({})return不足以终止连接并停止尝试发回额外的回复。

在我继续之前,我只想了解这里发生了什么,所以如果有人有任何提示或进一步阅读的链接(例如我在阅读此内容时错过的文档或 SO 帖子),我将非常感谢您的见解。

在向用户报告错误后让您的辅助函数返回false (如果没有错误,则返回true )并在调用它们时检查返回值:

async function checkCredits(user, res) {
  const credits = user.credits;
  if (credits <= 0) {
    res.json({ result: "failure" });
    return false;
  }
  return true;
}
app.post("/demonstration", async (req, res) => {
  const user = req.body.user;
  if (!(await checkCredits(user, res))) return;
  res.json({ result: "success" });
  return;
});

一个 function 中的返回仅终止 function,它不终止请求处理。

(A) 为什么 res 不能被传递(在第一个例子中)

它可以。 并且是。

(B) 为什么 res.json({}) 和 return 不足以终止连接并停止尝试发回额外的响应。

return只会停止当前的 function。

如果每次 function 一直停止return调用堆栈,这将不是很有用。 const foo = bar(); 将存在 function 在您可以对foo做任何事情之前!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM