typescript 使用Express处理Prisma错误

dsekswqp  于 2023-06-07  发布在  TypeScript
关注(0)|答案(2)|浏览(266)

我在使用ExpressJS和Prisma时遇到了一些错误处理问题。每当Prisma异常发生时,我的整个Node应用程序都会崩溃,我必须重新启动它。我已经做了一些谷歌搜索,并期待在Prisma Docs的错误处理,但我找不到任何答案。
我知道我可能会使用trycatch,但这感觉是不必要的,因为我可以用错误处理程序更好地处理这个问题,特别是当大量关于错误的信息通过Prisma传递时。
我试着像这样实现Express错误处理程序:

// index.ts

import errorHandler from "./middleware/errorHandler";
...
server.use(errorHandler);

// errorHandler.ts

import { NextFunction, Response } from "express";

// ts-ignore because next function is required for some weird reason
// @ts-ignore
const errorHandler = (err: any, _: any, res: Response, next: NextFunction) => {
    console.error(err.stack);
    res.status(500).send("Internal Server Error");
};

export default errorHandler;

这对正常错误很有效,但对Prisma错误不执行,而是只会使Node应用程序崩溃。
如何实现错误处理程序以便管理Prisma Expectations?

nukf8bse

nukf8bse1#

我今天遇到了这个问题,我也找不到答案。我相信我们必须为Prisma异常编写自己的自定义错误处理程序,而不是抛出错误。

try {
  await prismaOperation();
} catch(e) {
  throw e; // avoid this which will crash our app
  /* Process Prisma error with error codes
     and prepare an appropriate error message
  */
  const error = prismaCustomErrorHandler(e);
  res.send(error); // Sending response instead of passing it to our default handler
}

还有
// ts-ignore,因为由于某些奇怪的原因需要下一个函数
在Express中,错误处理函数有4个参数而不是3个:(err, req, res, next)
Express将带有3个参数的中间件函数解释为(req, res, next),这与省略第4个参数(err, _, res)不同。因此,Express不会传递任何错误,您的err将是req对象,_(req)是res对象,resnext函数。
编辑:

...
const error = prismaCustomErrorHandler(e);
  res.send(error); // Sending response instead of passing it to our default handler
...

// Edit: Or you could process and pass the error using `next(error)` to default error handler.

上面的方法不会使应用程序崩溃,并且确实会发送响应。但是无论使用next还是res.send,都必须处理错误。

luaexgnf

luaexgnf2#

到目前为止(Express < 5),Express仅在执行同步代码时遇到异常时才会自动调用错误处理程序。对于异步代码,您需要手动将错误传递给next()
Express error handling docs中所述:
在路由处理程序和中间件内的同步代码中发生的错误不需要额外的工作。如果同步代码抛出错误,Express将捕获并处理它。
对于由路由处理程序和中间件调用的异步函数返回的错误,您必须将它们传递给next()函数,Express将在其中捕获并处理它们。
您完全可以像这样对trycatch使用Express错误处理程序。

try {
  await prismaOperation();
} catch (e: unknown) {
  next(e);
}

如果你向next()函数传递任何东西(除了字符串'route'),Express会将当前请求视为错误,并跳过任何剩余的非错误处理路由和中间件函数。
如果prismaOperation抛出错误,catch块将执行,您必须手动将错误传递给next()。Express将跳过所有剩余的中间件并执行错误处理程序。
从Express 5开始,此行为将自动化,如文档中所述:
从Express 5开始,返回Promise的路由处理程序和中间件将在拒绝或抛出错误时自动调用next(value)。

相关问题