【问题标题】:{NodeJS} "Cannot set headers after they are sent to the client NodeJS"{NodeJS} "发送到客户端 NodeJS 后无法设置标头"
【发布时间】:2022-01-11 05:29:33
【问题描述】:

我在这里做错了什么? 我收到“错误 [ERR_HTTP_HEADERS_SENT]:在将标头发送到客户端 NodeJS 后无法设置标头”,有人可以帮我吗?

我正在使用:

快递 猫鼬(用于 MongoDB)

控制器

export const postResetPasswordEmail: Controller = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
   const { email } = req.body
   try {
      const errors: IValidatorError = getValidationErrors(req)
      if (Object.keys(errors).length !== 0) {
         res.status(403).json({ errors })
         return
      }
      const user = await User.findOne({ email })
      if (!user) {
         res.status(404).json({ message: AuthenticationErrors.noEmailFound })
         return
      } else {
         if (!(user.passwordUpdatedAt === undefined || (new Date(user.passwordUpdatedAt) < new Date()))) {
            res.status(404).json({ message: AuthenticationErrors.error10MinutesPassword })
            return
         }
      }
      const token = generateJWT({ email }, JWTKEY, '10m')
      await sendResetPasswordMail(email, token, next)
      res.status(200)
         .json({ message: SuccessMessages.resetPassword })
   } catch (err: any) {
      catchError(err, next)
   }
}

发送重置密码邮件

const sendResetPasswordMail: SendResetPasswordMail = async (userEmail: string, token: string, next: NextFunction): Promise<void> => {
   try {
      const transporter = nodemailer.createTransport({
         service: 'gmail',
         auth: {
            user: adminEmail.email,
            pass: adminEmail.pass
         }
      })
      const mailOptions = {
         from: adminEmail.email,
         to: userEmail,
         subject: 'Reset password',
         text: `Reset password: http://localhost:3000/resetPassword?token=${token}`
      }
      await transporter.sendMail(mailOptions)
   } catch (err: any) {
      catchError(err, next)
   }
}

生成JWT

const generateJWT: GenerateJWT = (userInfo: IUserInfo, JWTKEY: string, expireTime: string): string =>
   jwt.sign({ ...userInfo }, JWTKEY, { expiresIn: expireTime })

【问题讨论】:

  • 你能告诉我怎么做吗?
  • 哪个请求会出现该错误?请展示从请求开始到结束的所有代码,以便我们跟踪正在处理的请求的整个路径。
  • catchError() 是做什么的?
  • 我从控制器收到此错误。在其他的末尾。 (行)
  • const catchError: CatchError = (error: any, next: NextFunction): void =&gt; { !error.statusCode ? error.statusCode = 500 : null next(error) }

标签: javascript node.js typescript rest web


【解决方案1】:

我在 sendResetPasswordMail 中发现了一个缺陷: 假设你有一个异常,它在 sendResetPasswordMail catch 块中调用 catchError,在这种情况下,它会间接调用 next,而后者又会调用默认快速错误处理程序中的 res.status().send()。

尽管如此,尽管有异常 sendResetPasswordMail 会将控制权返回给您的控制器,该控制器将尝试在此之后发送状态 200,如果到那时错误处理程序已经发送了响应,您将收到错误消息。

有效的行为是不捕获 sendResetPasswordMail 中的异常并将其留给调用者。您还可以从 sendResetPasswordMail

中删除 next 参数

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2021-12-12
    • 2021-01-01
    • 2021-10-24
    相关资源
    最近更新 更多