【问题标题】:Why does this NodeJS code return empty response object?为什么这个 NodeJS 代码返回空响应对象?
【发布时间】:2020-07-30 20:51:21
【问题描述】:

这是代码:

router.post("/form", async (req, res) => {
  try {
    let { name, email, password } = req.body;
    let user = await User.create({
      name,
      email,
      password,
    });

    if (!user) return res.status(501).send("Something went wrong");
    let token = await user.getSignedToken();
    console.log(token); //Server logs this

user.emailToken = await user.verifyEmail();// This property is not being added in the saved mongodb document. It should, but again idk why it's not

    await user.save({ validateBeforeSave: false });
    console.log(user); // Server doesn't log this
    const options = {
      expires: new Date(
        Date.now() + process.env.JWT_COOKIE_EXPIRE * 24 * 60 * 60 * 1000
      ),
    };
    console.log(options); // Server doesn't log this
    res.cookie("token", token, options);
    res.send("Check email for activation");
  } catch (ex) {
    res.send(ex);
  }
});

下面是 verifyEmail 方法(在 userSchema.. 我用的是 mongoose):

userSchema.methods.verifyEmail = async function () {
  let emailToken = this._id + crypto.randomBytes(10).toString("hex");
  let emailTokenHashed = await crypto
    .createHash("sha256")
    .update(passwordToken)
    .digest("hex");
  this.emailToken = emailTokenHashed;

  return emailToken;
};

现在,它应该发送“检查电子邮件以进行激活”,对吗?但是,它发送的是一个空的响应对象。此外,如果您在代码中看到,服务器只记录一个 console.log(即第一个 console.log)。但是,它正在发送一个 cookie(我通过邮递员检查过)。那么,这里有什么问题呢?

【问题讨论】:

  • 创建哈希时不需要等待cryptonodejs.org/dist/latest-v12.x/docs/api/…
  • 这不是您问题的答案,但为什么不在您的 Schema 方法中调用 this.save() 而不是先调用 user.emailToken = await user.verifyEmail() 然后保存?或者你也可以只做await user.verifyEmail()而不将它设置为user.emailToken,因为它已经在Schema方法中设置了,不是吗?我在这里错过了什么吗?
  • @jfriend00 不,它没有。它发送一个空对象作为响应

标签: node.js express


【解决方案1】:

此代码发送res.send("Check email for activation");res.send(ex);。既然你这么说:

console.log(options); // Server doesn't log this

那么您的await 语句之一必须满足被拒绝的承诺并将您发送到catch。在res.send(ex) 之前添加console.log(ex) 以查看错误是什么所以你有这个:

} catch (ex) {
    console.log("got error", ex);
    res.send(ex);
}

然后,看看你在日志中得到了什么。

一般来说,您永远不想直接发送错误对象,因为它的大多数属性都是不可枚举的,因此它们不会以 JSON 格式发送,这可能会使错误对象完全为空被转换为 JSON,因此对客户端根本没有用。相反,在您的服务器上记录错误并发送 500 状态:

res.sendStatus(500);

或者,如果您想发送一个错误对象,请使用常规的可枚举属性构建您自己的错误对象并发送它。

无论如何,一旦您将console.log(ex) 添加到您的服务器,它应该会告诉您实际被拒绝的承诺是什么,并且会告诉您请求出了什么问题。始终在服务器上记录错误以帮助您查看和解决此类问题。

【讨论】:

  • 首先,我收到一个空对象作为响应。其次,我尝试了 console.log(ex) 但它没有记录任何异常
  • @Zain763 - console.log(ex) 究竟记录了什么?您的代码只有两个您要发送响应的地方。一个发送一个字符串,另一个发送一个对象。如果您从响应中返回一个对象,逻辑会说您正在访问发送该对象的代码路径。你需要调试为什么会这样。
  • console.log(ex) 根本没有记录任何内容。这就是我不明白的。它不记录 2 个控制台日志语句。它不记录异常。它不会发送所需的响应,但它正在设置 cookie。这就是我不明白的问题。已经工作了好几个小时了。
  • @Zain763 - 那么,await user.verifyEmail();await user.save({ validateBeforeSave: false }); 必须是拒绝/抛出。您必须弄清楚是哪一个并从中捕获错误消息以查看原因。你可以用他们自己的try/catch 包围每个人,并使用他们自己单独的错误日志记录,以确保他们的错误得到输出,这样你就可以看到哪个被击中了。
  • @Zain763 - 请同时更改您的代码,这样您就不会在catch 中执行res.send(ex);,因为这对调用者没有用处。您应该发送错误状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 2021-12-30
相关资源
最近更新 更多