gpt4 book ai didi

typescript - Guards 和循环依赖中的服务注入(inject)

转载 作者:行者123 更新时间:2023-12-05 05:43:34 25 4
gpt4 key购买 nike

我目前正在为守卫中的服务注入(inject)而苦苦挣扎。

好吧,我做了一个 JwtAuthGuard,它需要我的 FirebaseServiceUserService

所以我认为创建一个 AuthGuardModule 会很有用,所以我只需要在具有 Controller 的模块中导入我的 AuthGuardModules >,使用我的守卫。

不幸的是,我的 UserModule 也需要这个守卫。所以当我在我的 UserModule 中导入我的 AuthGuardModule 时,我得到一个 Circular Dependency Error 是很自然的。

然后,我在 Nest.js 中尝试了所有与 Circular Dependency Error 或多或少相关的事情,但无能为力。

有人可以告诉我如果:

  • 我想只为我的守卫制作一个模块是完全错误的吗?
  • 如果不是,我该如何修复我的Circular Dependency Error
  • 如果我误解了那部分,为什么它不对,最好的方法是什么?

JwtAuthGuard

@Injectable()
export class JwtAuthGuard implements CanActivate {
private readonly logger = new Logger(JwtAuthGuard.name)

constructor(
private readonly firebaseService: FirebaseService,
private readonly userService: UserService
) { }

async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers['authorization'];

if (!token) {
throw new UnauthorizedException
}

try {
const firebaseUser = await this.firebaseService.getUserByToken(token)
request.user = await this.userService.getByEmail(firebaseUser.email)
return true
} catch (error) {
this.logger.error(this.canActivate.name, error)
throw new UnauthorizedException
}
}
}

AuthGuardModule

@Module({
imports: [UserModule],
providers: [FirebaseService, JwtAuthGuard],
exports: [JwtAuthGuard]
})

export class AuthGuardModule {}

编辑

好吧,NestJS discord 的 jmcdo29 向我解释说:

Your AuthGuardModule should export the UserModule and the FirebaseService. Guards, when used in the @UseGuards() decorator, are used in the context of the current controller's module, instead of being looked at as an Injectable provider

所以我这样做了,它确实解决了我最初的问题,但我还有另一个循环依赖问题。

首先,让我们恢复一下我的架构:

授权模块

  • 它处理注册路由,以及发送一些电子邮件的路由,如密码重置或电子邮件验证。
  • 当我调用 register 路由时,它需要 UserModule 在我的数据库中创建一个用户
@Module({
imports: [
AuthGuardModule
],
controllers: [AuthController],
providers: [AuthService, EmailService, FirebaseService],
})

export class AuthModule {}

文件模块

  • 它处理文件的上传和删除。
@Module({
imports: [
forwardRef(() => AuthGuardModule),
BlobModule,
MongooseModule.forFeature([{ name: File.name, schema: FileSchema }])
],
controllers: [FileController],
providers: [FileService],
exports: [FileService],
})

export class FileModule {}

用户模块

  • 它处理所有用户路由。
  • 它需要 FileModule,在修改头像时检查头像是否存在(我只有一个路径可以更新我所有用户的个人数据)
  • 它还需要 AuthGuardModule 来使用我的 JwtAuthGuard
@Module({
imports: [
forwardRef(() => AuthGuardModule),
forwardRef(() => FileModule),
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])
],
controllers: [UserController],
providers: [UserService, FirebaseService],
exports: [UserService, FileModule]
})

export class UserModule {}

AuthGuardsModule

  • 它包含我的 JWT 检查守卫,然后我检查我的数据库中的用户是否链接到已连接的用户
  • 它需要 UserModule 来获取我的数据库中的用户
@Module({
imports: [forwardRef(() => UserModule), FirebaseModule],
providers: [JwtAuthGuard, RegisterAuthGuard],
exports: [JwtAuthGuard, RegisterAuthGuard, FirebaseModule, UserModule]
})

export class AuthGuardModule {}

我可以使用 firebase 来存储我的用户头像并在前端进行,但我必须将它存储在 Azure Blob 存储中(这是强加给我的),所以 FileModule 会处理所有这些事情

所以,现在,感谢你们,我解决了我的 AuthGuardsModule -> UserModule 循环依赖,我有一个新的循环依赖问题:AuthGuardsModule -> UserModule -> FileModule

我在 FileModule 中设置了 AuthGuardsModule 的 forwardRef,但 nest 自然地告诉我要确保双向关系的每一侧都用“forwardRef()”装饰

所以我在 UserModule 中将 forwardRef 导入到我的 FileModule 中,但同样如此。

有什么想法吗?

最佳答案

从我的角度来看,您需要使用 @nestjs/common 包中的 forwardRef 方法,它负责在循环依赖发生时处理它.参见 Circular dependency - NestJS docs

需要考虑的一件事是您的 JwtAuthGuard 的位置。它最初是在 AuthModule 中还是在另一个共享模块中?

我假设守卫最初在您的 AuthModule 中(例如,假设 /src/auth/guards/auth-guard.ts)。
我还假设 FirebaseService 位于 FirebaseModule 中并从那里导出,并且 FirebaseModule 可注入(inject)不需要其他类取决于其他循环引用类/模块。 (在这种情况下,您需要通过在涉及的类/模块中添加更多 forwardRef 来指示 Nest 应如何处理它)

根据您提供的代码,您可以执行如下操作:

授权模块

@Module({
imports: [forwardRef(() => UserModule), FirebaseModule],
providers: [...yourProviders],
exports: [...yourExportedInjectables]
})

export class AuthModule {}

FirebaseModule

@Module({
imports: [...requiredImports],
providers: [FirebaseService],
exports: [FirebaseService]
})

export class FirebaseModule {}

用户模块

@Module({
imports: [forwardRef(() => AuthModule)],
providers: [...yourProviders],
exports: [...yourExportedInjectables]
})

export class UserModule {}

注意:您还可以根据具体用例在服务层使用forwardRef
NB2:守卫可以在一个共享模块中分组,该模块可以导入到 AuthModule 中,这样您就不必指定 Nest 在每个模块之间转发引用,而只需引用 AuthModule 在使用给定守卫的模块中。

希望对你有帮助!
同样,我对您的架构了解不多,因此我提供了基于假设的代码示例。
不要犹豫,发表评论/提供更多上下文,以便我可以相应地编辑我的答案。

关于typescript - Guards 和循环依赖中的服务注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71778848/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com