如何解决NestJs:将服务或其他任何东西注入导入的模块
有没有比下面更好的方法将服务或组件注入到导入的模块中?
export interface AmqpInterceptor{
after(message:any):Promise<void>;
}
export class AmqpInterceptors extends Array<AmqpInterceptor>{
}
//generic library module
@Module({
providers:[{
provide: AmqpInterceptors,useValue: []
}]
}
export class AMQPModule implements OnModuleInit{
static register(options: AMQPOptions): DynamicModule {
const providers = options.providers || []
return {
module: AMQPModule,providers: [
...providers,OtherProvider
]
}
}
}
//end user module
@Module({
imports: [
AMQPModule.register(({
// I had to create a factory method to pass providers as an argument.
// I would think that it is not a good practice
providers: [{
provide:AmqpInterceptors,useValue:[MyCustomInterceptor]
}]
})
],providers: [
]
})
export class QueueModule {
}
当前有效的解决方案:我在通用模块中声明了一个默认的空数组,并在工厂方法中声明了允许在模块构造中传递自定义值的工厂方法。(在我最幸福的世界中,我声明了一个接口的多个实例,然后,DI收集了所有这些,但是我认为这在NestJs中实际上是不可能的)
解决方法
您可以使用@golevelup/nestjs-discovery之类的软件包来帮助您。
基本上,您必须执行以下操作:
// AMQP模块
// amqp-interceptor.decorator.ts
import { SetMetadata } from '@nestjs/common';
export function AmqpInterceptor() {
return SetMetadata('AMQP_INTERCEPTOR',true)
}
// amqp-explorer.ts
import { OnModuleInit } from '@nestjs/common'
@Injectable()
export class AmqpExplorer implements OnModuleInit {
constructor(
private readonly discoveryService: DiscoveryService,) {}
async onModuleInit(): Promise<void> {
const amqpInterceptorProviders = await this.discoveryService.providers('AMQP_INTERCEPTOR')
// you can store this list,to be queried by some
// other provider to use interceptors,etc.
}
}
// amqp.module.ts
@Module({ providers:[AmqpExplorer]})
export class AMQPModule { }
//最终用户模块
// end-user.module.ts
@Module({ imports:[AMQPModule],providers: [SomeAmqpInterceptor] })
export class EndUserModule { }
// some-amqp.interceptor.ts
@Injectable()
@AmqpInterceptor()
export class SomeAmqpInterceptor {
run(): void { console.log('intercepting') }
}
肥胖:
- 拦截器装饰器:您可以添加任何有助于改善api的参数
- 我建议使用此列表(提供程序列表),而不是将经过修饰的提供程序注入模块中,因为我不知道您打算如何使用它们。这样,您就有了一个提供程序列表,可以调用每个提供程序。
-
AMQP_INTERCEPTOR
字符串可能会与其他一些元数据发生冲突,这是一种很好的做法,请添加更具体的内容以避免模块中两个元数据相同的元数据 - 要稍后调用拦截器,请执行以下操作:
import { ExternalContextCreator } from '@nestjs/core/helpers/external-context-creator'
export class Runner {
constructor(
private readonly handler: DiscoveredMethodWithMeta,private readonly externalContextCreator: ExternalContextCreator,) { }
run(): void {
const handler = this.externalContextCreator.create(
this.handler.discoveredMethod.parentClass.instance,this.handler.discoveredMethod.handler,this.handler.discoveredMethod.methodName,)
const handlerResult = await handler(content)
}
- 不是在本地运行,但我认为这是一个很好的起点
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。