javascript - 我如何组织在 NestJs 服务中抛出业务逻辑异常?

标签 javascript node.js typescript architecture nestjs

我对这个 github 问题讨论有一些疑问:https://github.com/nestjs/nest/issues/310

我想按照 shekohex 的建议从我的服务方法中抛出业务域异常。我想知道我应该把它们放在哪里?我相信它们中的许多在不同领域(如 EntityNotFoundExceptionActionForbiddenException 等)将非常相似,因此将它们保留在应用程序级别(某种共享的模块)。另一方面,这使得特定领域的独立性降低(例如,如果我需要在未来某个时间将其中的一些提取到另一个应用程序中怎么办?)。此外,一些异常可能是特定于域的,我必须将它们保存在适当的域模块结构中。

假设我确实将其中一些保留在共享模块中,其余的保留在单独的域目录中。如何将它们映射到正确的 HttpExceptions?如果我制作全局异常过滤器,我也会让我的域 Controller 更加依赖于应用程序层。如何映射特定于域的异常?我是否创建另一个模块级异常过滤器?

创建全局或模块级过滤器是否可行?用 UseFilters 装饰每个端点似乎很麻烦。

预先感谢您的输入!

最佳答案

这是我最近一直在处理的一个很好的问题。

对于某些项目,我们希望在应用程序的不同域之间共享业务错误。我们最终得到的是简单地拥有一个共享(或公共(public))文件夹或模块,以暴露我们在应用程序中遇到的不同域特定错误。

最重要的是,我们使用了 Nest 的常见异常,它们非常适合这项工作!

最后,我们使用共享域特定的业务错误自定义常见的 Nest 异常。

极简user.service.ts复制示例:

import { NotFoundException, Logger } from '@nestjs/common';
import { UserBusinessErrors } from '../../shared/errors/user/user.business-errors';

// some code ...

// Find the users from the usersIds array
const dbUsers = await this.userRepository.find({ id: In(usersIds) });
// If none was found, raise an error
if (!dbUsers) {
    Logger.error(`Could not find user with IDs: ${usersIds}`, '', 'UserService', true);
    throw new NotFoundException(UserBusinessErrors.NotFound);
}

与其相应的 user.business-errors.ts 文件在共享或公共(public)模块/文件夹中(例如 src/shared/errors/user/user.business-errors.ts):

export const UserBusinessErrors = {
    // ... other errors

    NotFound: {
        apiErrorCode: 'E_0002_0002',
        errorMessage: 'User not found',
        reason: `Provided user ids doesn't exist in DB`
    },

    // ... other errors
}

或者有时如果你想要更通用的东西,你也可以使用共享错误:

import { InternalServerErrorException, Logger } from '@nestjs/common';
import { SharedBusinessErrors } from '../../shared/errors/shared.business-errors';

// some code ...

try {
    // ...
} catch (error) {
    Logger.log(SharedBusinessErrors.DbSaveError, 'UserService');
    throw new InternalServerErrorException(SharedBusinessErrors.DbSaveError, error.stack);
}

与相应的 shared.business-errors.ts 文件:

export const SharedBusinessErrors = {
    DbSaveError: {
        apiErrorCode: 'E_0001_0001',
        errorMessage: `Error when trying to save resource into the DB`,
        reason: 'Internal server error'
    },

    // ... other errors
}

评论您的不同问题的最后想法:

  • 如你所说

Is creating global- or module-level filters a way to go? Decorating every endpoint with UseFilters seems pretty cumbersome.

  • 我们可以利用 Nest filters customization并在 Controller 或路由级别也使用装饰器。但对我来说,您实际上仍然需要指定它与哪些业务错误相关,以便为您的业务错误增加值(value)并且您无论如何都需要在您的服务中引发错误。因此,仅包含一些包含域特定(或业务)错误的共享文件和更通用的错误在我看来是很好的(但可能不是最干净/最优雅的解决方案)。

  • 您可以将您的业务错误文件放在每个模块的文件夹中,并添加一个 webpack 配置以将所有这些文件收集并连接到一个唯一的文件中。

最后,如果您需要跨多个项目的特定领域或共享错误,我想您甚至可以创建一个 npm 包。

如果我对任何事情不清楚或/以及它是否能给您更多见解,请告诉我!

关于javascript - 我如何组织在 NestJs 服务中抛出业务逻辑异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57568559/

相关文章:

javascript - 如何在不刷新页面的情况下查看更新的列表

angular - Angular 2 中的简单 ngFor 错误

javascript - 动态生成多个 d3 svg 图

javascript - 文档就绪与正文就绪与窗口就绪事件

javascript - 如何创建多个表并在每个表中存储json数据

node.js - 将 Node 注册为 js 文件的默认可执行文件

javascript - TypeScript - 'Unexpected token' 用于异步函数前缀

php - 按时间戳条目聚合和可视化 SQLite 数据库中的条目

json - Mongoose 多对多关系和 JSON 循环结构

javascript - 如何处理 puppeteer-cluster[CONCURRENCY_BROWSER] 中的多个选项卡?