【问题标题】:NodeJs UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the clientNodeJs UnhandledPromiseRejectionWarning:错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端后无法设置标头
【发布时间】:2020-11-01 12:12:01
【问题描述】:

您好,我正在使用中间件进行用户验证任务来验证用户是否存在,这是我的代码:

我有一个这样定义的端点:

app.get("/login/", verifyUser, userController.login); 

这是我的中间件 verifyUser:

function verifyUser(req, res, next) {
  console.log("Midd 1:", req.query);
  let userInfo = userController.findUserOne(req, res);
  console.log("userInfo:" + userInfo);
  next();
}

这是我的控制器方法:

exports.findUserOne = function (req, res) {
  (async () => {
    try {
      var query = db
        .collection("users")
        .where("user", "==", req.query.user)
        .where("password", "==", req.query.password);
      query.get().then(function (querySnapshot) {
        if (querySnapshot.size > 0) {
          const accessToken = generateAccessToken({ name: req.query.user });
          res.json({ accessToken: accessToken });
        } else {
          return res.status(500).send("User doesn't exist:");
        }
      });
    } catch {
      return res.status(500).send(error);
    }
  })();
};

调用登录端点后,我收到下一条错误消息:

(node:12468) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:485:11)
    at ServerResponse.header (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:771:10)
    at ServerResponse.send (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (C:\Tools\Node\From Github\NodeAndReact-FullStack\server\node_modules\express\lib\response.js:267:15)
    at C:\Tools\Node\From Github\NodeAndReact-FullStack\server\controllers\users\userController.js:54:15
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(node:12468) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:12468) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

我正在通过 try, catch 处理控制器中的异步块,但根据外观,问题似乎与此有关。事实上,我不太确定这是否是实现此验证的最佳方式,或者我遇到了与异步代码相关的问题。

【问题讨论】:

    标签: node.js async-await middleware


    【解决方案1】:

    当响应已经发送给用户时,会发生错误Error [ERR_HTTP_HEADERS_SENT]。这里userController.findUserOne(req, res)async。所以 js 不等待它并调用next()。这会产生竞争条件。

    中间件不应该直接调用控制器方法,因为这些方法最终会向用户发送请求。您可以创建一个 utils 文件夹,其中可以包含执行所有这些逻辑操作的文件并将数据返回到 middelware 而不向用户发送响应。此外,您需要与.then() 链接以等待结果,然后在其中调用next()

    但我猜你可能想将所有这些逻辑转移到userController.login。不需要单独的中间件。

    【讨论】:

      【解决方案2】:

      这是因为 userController.findUserOne 是一个异步函数,而您调用它时没有任何等待。所以在这部分代码中

      function verifyUser(req, res, next) {
          console.log("Midd 1:", req.query);
          let userInfo = userController.findUserOne(req, res);
          console.log("userInfo:" + userInfo);
          next();
      }
      

      当您调用 userController.findUserOne(req, res); 时,因为异步函数返回一个 Promise,它也将返回一个 Promise,而不是您想要的真实用户信息。

      解决方案是将 verifyUser 函数更改为以下内容:

      async function verifyUser(req, res, next) {
          try {
              console.log("Midd 1:", req.query);
              let userInfo = await userController.findUserOne(req, res);
              console.log("userInfo:" + userInfo);
              next();
          } catch(error){
              //handle exceptions here
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-09-28
        • 2021-10-11
        • 1970-01-01
        • 2020-05-26
        • 2018-09-19
        • 2020-09-22
        • 1970-01-01
        • 2023-01-19
        相关资源
        最近更新 更多