如何在NestJS中根据调用模块向CommonService构造器传参?
问题:根据调用位置为CommonService传递不同构造器参数
现有文件结构
/src ├── common/ │ ├── common.module.ts │ └── common.service.ts (CommonService) └── myclass/ ├── myclass.module.ts ├── myclass.service.ts (MyClassService) ├── another-class.module.ts └── another-class.service.ts (AnotherClassService)
需求说明
需要从/src/myclass/myclass.module.ts和/src/myclass/another-class.module.ts中传递变量到/src/common/common.service.ts的构造器,使得CommonService根据调用位置初始化不同变量:被MyClassService调用时传入值"1",被AnotherClassService调用时传入值"0"。
回答:可行,两种实现方案
基于NestJS的依赖注入机制,我们可以通过自定义提供者或动态模块两种方式实现需求,以下是具体步骤:
方案一:自定义令牌区分实例
通过为CommonService创建不同的注入令牌,让不同模块注入对应配置的实例。
1. 修改CommonService接收构造参数
// src/common/common.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class CommonService { private readonly flag: string; constructor(flag: string) { this.flag = flag; } // 示例方法,验证参数是否生效 getFlag(): string { return this.flag; } }
2. 在CommonModule中定义令牌和提供者
// src/common/common.module.ts import { Module, Provider } from '@nestjs/common'; import { CommonService } from './common.service'; // 定义自定义令牌,用于区分不同实例 export const COMMON_SERVICE_FLAG_1 = 'COMMON_SERVICE_FLAG_1'; export const COMMON_SERVICE_FLAG_0 = 'COMMON_SERVICE_FLAG_0'; // 创建两个不同配置的CommonService提供者 const commonServiceProviders: Provider[] = [ { provide: COMMON_SERVICE_FLAG_1, useFactory: () => new CommonService('1'), }, { provide: COMMON_SERVICE_FLAG_0, useFactory: () => new CommonService('0'), }, ]; @Module({ providers: [...commonServiceProviders], exports: [...commonServiceProviders], // 导出供其他模块调用 }) export class CommonModule {}
3. 在MyClass模块注入对应实例
// src/myclass/myclass.module.ts import { Module } from '@nestjs/common'; import { CommonModule } from '../common/common.module'; import { MyClassService } from './myclass.service'; @Module({ imports: [CommonModule], providers: [MyClassService], }) export class MyClassModule {}
// src/myclass/myclass.service.ts import { Inject, Injectable } from '@nestjs/common'; import { CommonService } from '../common/common.service'; import { COMMON_SERVICE_FLAG_1 } from '../common/common.module'; @Injectable() export class MyClassService { constructor( @Inject(COMMON_SERVICE_FLAG_1) private readonly commonService: CommonService, ) {} test() { console.log(this.commonService.getFlag()); // 输出 "1" } }
4. 在AnotherClass模块注入另一实例
// src/myclass/another-class.module.ts import { Module } from '@nestjs/common'; import { CommonModule } from '../common/common.module'; import { AnotherClassService } from './another-class.service'; @Module({ imports: [CommonModule], providers: [AnotherClassService], }) export class AnotherClassModule {}
// src/myclass/another-class.service.ts import { Inject, Injectable } from '@nestjs/common'; import { CommonService } from '../common/common.service'; import { COMMON_SERVICE_FLAG_0 } from '../common/common.module'; @Injectable() export class AnotherClassService { constructor( @Inject(COMMON_SERVICE_FLAG_0) private readonly commonService: CommonService, ) {} test() { console.log(this.commonService.getFlag()); // 输出 "0" } }
方案二:动态模块传递配置
通过forRoot方法让每个模块传入自定义配置,生成独立的CommonService实例。
1. 将CommonModule改为动态模块
// src/common/common.module.ts import { DynamicModule, Module, Provider } from '@nestjs/common'; import { CommonService } from './common.service'; // 定义配置参数类型 export interface CommonModuleOptions { flag: string; } @Module({}) export class CommonModule { static forRoot(options: CommonModuleOptions): DynamicModule { const serviceProvider: Provider = { provide: CommonService, useValue: new CommonService(options.flag), }; return { module: CommonModule, providers: [serviceProvider], exports: [serviceProvider], }; } }
2. 在MyClassModule中传入配置
// src/myclass/myclass.module.ts import { Module } from '@nestjs/common'; import { CommonModule } from '../common/common.module'; import { MyClassService } from './myclass.service'; @Module({ imports: [CommonModule.forRoot({ flag: '1' })], providers: [MyClassService], }) export class MyClassModule {}
3. 在AnotherClassModule中传入另一配置
// src/myclass/another-class.module.ts import { Module } from '@nestjs/common'; import { CommonModule } from '../common/common.module'; import { AnotherClassService } from './another-class.service'; @Module({ imports: [CommonModule.forRoot({ flag: '0' })], providers: [AnotherClassService], }) export class AnotherClassModule {}
此时两个模块中的CommonService实例完全独立,各自使用传入的flag值。
内容的提问来源于stack exchange,提问作者Shehzad Nizamani
相关产品推荐
相关产品推荐

