Nest.js 没有构造函数的 Mongoose 模型依赖注入

Nest.js Model Dependency Injection with Mongoose with no constructor

我需要将 CRM API 与我在 Nest.js 中的服务集成。不幸的是,他们要求我实现他们的接口以使用自定义持久层,在我的例子中,Mongo。由于我需要实例化生成的 class,因此我无法像往常一样注入模型,因此我尝试在 class 成员变量上使用它。但是这样会导致成员变量未定义的错误。

这是我的猫鼬模型:

export type ZohoTokenDocument = ZohoToken & Document;

@Schema({ timestamps: true })
export class ZohoToken {
  @Prop()
  name: string;

  @Prop({ type: String, length: 255, unique: true })
  user_mail: string;

  @Prop({ type: String, length: 255, unique: true })
  client_id: string;

  @Prop({ type: String, length: 255 })
  refresh_token: string;

  @Prop({ type: String, length: 255 })
  access_token: string;

  @Prop({ type: String, length: 255 })
  grant_token: string;

  @Prop({ type: String, length: 20 })
  expiry_time: string;
}

export const ZohoTokenSchema = SchemaFactory.createForClass(ZohoToken);

这是我根据第 3 方的要求创建的自定义 class API:

export class ZohoStore implements TokenStore {
  @InjectModel(ZohoToken.name)
  private readonly tokenModel: Model<ZohoTokenDocument>;

  async getToken(user, token): Promise<any> {
    const result = await this.tokenModel.findOne({ grant_token: token });
    return result;
  }
...

在我的服务中,我只是将此 class 实例化为 new ZohoStore(),在稍后调用 getToken() 方法之前它工作正常。

产生的错误是:"nullTypeError: Cannot read property 'findOne' of undefined",,这对我来说意味着 tokenModel 没有被实例化。知道如何将我的模型注入此 class 而无需将其放入构造函数中,否则我无法使用服务中的零参数构造函数实例化它吗?

如果您尝试使用 Nest DI 系统,那么您不能自己调用​​ new ZohoStore(),因为 Nest 没有机会实例化 ZohoStore 的依赖项。

您需要将其注册为某个 NestJS 模块中的提供程序,然后如果需要,可以检索由 NestJS 创建的实例

为了添加到@Micael 的回复中,您需要执行以下操作:

  1. 将商店添加到将使用 DI 的模块:
@Module({
  imports: [MongooseModule.forFeature([{ name: ZohoToken.name, schema: ZohoTokenSchema }])],
  exports: [ZohoStore, ZohoService],
  providers: [ZohoStore, ZohoService],
  controllers: [ZohoController]
})
export class ZohoModule {}
  1. 务必将 @Injectable() 装饰器添加到 Store class 并使用 DI 注入模型:
@Injectable()
export class ZohoStore implements TokenStore {
  constructor(@InjectModel(ZohoToken.name)
  private readonly tokenModel: Model<ZohoTokenDocument>){};
  1. 在服务 class 中,如下引用 ZohoStore 所以当您准备好使用它时,您只需从 class 成员变量中调用 this.zohoStore 而不是尝试用 new:
  2. 实例化它
@Injectable()
export class ZohoService {
  private zohoStore: ZohoStore;

  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    this.zohoStore = this.moduleRef.get(ZohoStore);
  }