NestJs或TypeScript是否提供诸如';KeyNotFoundException';

NestJs或TypeScript是否提供诸如';KeyNotFoundException';,typescript,nestjs,Typescript,Nestjs,我想创建一个NestJs后端,从一些REST端点开始,但稍后也希望支持GraphQL 假设我想按id删除一个用户。服务层通过检查已删除行的数量来知道该用户是否已被删除。如果不是零,则用户已被删除。如果它是零,我想抛出一个“未找到异常” 我知道Nest附带了一些预先生成的http异常。但是我不想在我的服务层中使用这些异常,因为我认为它们应该只在HTTP层(REST控制器)中使用 所以我创建了自己的异常 export class KeyNotFoundException extends Error

我想创建一个NestJs后端,从一些REST端点开始,但稍后也希望支持GraphQL

假设我想按id删除一个用户。服务层通过检查已删除行的数量来知道该用户是否已被删除。如果不是零,则用户已被删除。如果它是零,我想抛出一个“未找到异常”

我知道Nest附带了一些预先生成的http异常。但是我不想在我的服务层中使用这些异常,因为我认为它们应该只在HTTP层(REST控制器)中使用

所以我创建了自己的异常

export class KeyNotFoundException extends Error {
  constructor(message: string) {
    super(message);
  }
}
并在我的服务层和存储库层中使用它们

public async deleteUserById(id: number): Promise<void> {
  const deletedRows: number = await this.usersRepository.deleteUserById(id);

  if (deletedRows === 0) {
    // my custom exception
    throw new KeyNotFoundException(`User with Id ${id} not found`);
  }
}
我对该解决方案不满意,因为我一直在将自定义异常转换为NestJs HTTP异常。也许服务会出现多个异常,我必须使用一个开关来检查正确的异常类型

有没有更好的办法来解决这个问题


例如,C#附带了一个,但我认为对于TypeScript,我必须创建自己的异常系统。

首先,我认为您当前的解决方案是完全有效的。如果您不想从服务中抛出http异常并在控制器中抛出NotFound,则无法转换这两者。为了方便起见,您可以创建一个通用异常工厂,它知道如何将服务异常转换为http异常。您也可以将其作为中间件的一部分来处理,而不用在控制器端担心它

嘿,谢谢您的回复。请您再描述一下您的解决方案好吗?通用工厂将充当映射器?你说的中间件是什么意思,我认为它只在控制器请求到来之前运行。NestJs管道也一样?那么,你是否有一个转变的想法?:)我对您的通用工厂方法非常感兴趣,因为我仍然需要一个Hashmap或其他东西来映射它。看起来您对内置的NestJs解决方案有一个很好的建议。。。一般来说,我会创建一个
ExceptionType-->HttpExceptionType
的映射,然后对于捕获的每个异常,我会检查它是否存在于键中,如果存在,我会获取相关的
HttpExceptionType
,并将捕获的异常实例化为内部异常查看
异常过滤器。通过使用
app.useGlobalFilters()
将所有异常映射到同一位置,您可以拥有一个全局异常筛选器,但我建议根据您的控制器将它们分开。谢谢,我了解了这一点,并看到它们处理HttpExceptions并向客户端返回自定义响应。因此,我应该创建多个筛选器来映射这些异常并返回匹配的HttpException?在一个筛选器中,您可以捕获退出控制器的所有异常,并将它们映射到正确的http代码。注释
@Catch()
可以接受多个异常。但如果您想更具体一些,可以为控制器的每个入口点创建过滤器。我在这里得到了一个例子,我捕获了我自己的异常,如果它可以帮助您:嗯,是的,您正在使用
if(error instanceof…
也:)我想我可以使用全局过滤器,然后为每个自定义异常创建一个异常过滤器,对吗?像
@Catch(KeyNotFoundException)
将返回NestJs
NotFoundException
是,您可以同时使用全局筛选器和特定筛选器。另外,我刚刚查找了一下,您可以在
UseFilters()
中添加多个过滤器,这样您就可以为每个自定义异常都添加一个过滤器,但我从未尝试过。是的,
@Catch(KeyNotFoundException)
就是这样:)
@Delete(':id')
public async deleteUserById(@Param('id', ParseIntPipe) id: number): Promise<void> {
  try {
    await this.usersService.deleteUserById(id);
  } catch (error) {
    // my custom Exception
    if (error instanceof KeyNotFoundException) {
      // premade NestJs exception will throw 404
      throw new NotFoundException(error.message);
    }

    // premade NestJs exception will throw 500
    throw new InternalServerErrorException();
  }
}