typescript 为什么Node.js在Express中处理错误时会崩溃,Headers已经发送了Error

twh00eeo  于 2023-05-30  发布在  TypeScript
关注(0)|答案(1)|浏览(261)

我正在使用Express为用户注册创建一个API端点。问题是,每当我向该API端点发送一个将引发错误的请求时,我的node.js服务器就会崩溃并给我以下消息:

node:internal/errors:491
[1]     ErrorCaptureStackTrace(err);
[1]     ^
[1]
[1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent 
to the client
[1]     at new NodeError (node:internal/errors:400:5)
[1]     at ServerResponse.setHeader (node:_http_outgoing:663:11)
[1]     at ServerResponse.header (D:\...\node_modules\express\lib\response.js:794:10)
[1]     at ServerResponse.send (D:\...\node_modul

因此,node.js服务器在发送错误(失败)响应时会崩溃,但在发送成功响应时不会崩溃。所以我想我在这里没有正确地处理错误?
我做错了什么?下面是我的实现:

const registerUser = async (req: Request, res: Response) => {
  try {
    const userData = createUserSchema.parse(req.body) as User;

    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(userData.password, salt);

    const user = await db.user.create({
      data: {
        ...userData,
        password: hashedPassword,
      },
    });

    return res.status(201).json({
      status: 'success',
      data: { name: user.name, email: user.email },
    });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return res.status(422).json({
        status: 'fail',
        message: error.issues,
      });
    } else if (error instanceof Prisma.PrismaClientKnownRequestError) {
      if (error.code === 'P2002') {
        return res.status(409).json({
          status: 'fail',
          message: 'Email address is already in use',
        });
      }
    }

    return res.status(500).json({
      status: 'fail',
      message: 'Something went wrong',
    });
  }
};

我尝试只在一种情况下返回error,看看这些响应是否冲突,但即使我只有一个响应,node.js服务器也会崩溃。

qvtsj1bj

qvtsj1bj1#

发生此错误的原因是,您试图在响应标头已发送到客户端之后设置它们。在Express中,您不能在发送响应正文部分后设置响应标头。当您尝试在已发送响应正文部分或成功响应之后发送错误(失败)响应时,会发生此错误。
要解决这个问题,请确保在代码中正确处理错误。请确保不要为单个请求向客户端发送多个响应。您可以使用Express Error Handling Middleware捕获错误并向客户端发送适当的响应,而不会抛出“ERR_HTTP_HEADERS_SENT”错误。
尝试使用中间件,如下所示:
app.use((err,req,res,next)=> { console.error(err);
res.status(500).json({ status:“失败”,消息:'出错了',});});
https://expressjs.com/en/guide/using-middleware.html
使用express中间件将为您节省大量的精力

相关问题