未初始化调用类函数:NestJS中ExampleService实例化报错问题
问题根源
你在TelegrafModule里能直接用ExampleService不用传参数,是因为NestJS的依赖注入(DI)容器在背后帮你做了所有事:它会自动解析ExampleService的所有依赖、创建实例,然后注入到你的类里。
但layouts.telegraf.ts里的是普通函数,不在Nest的DI容器管理范围内,手动new ExampleService()就必须自己传入它要求的所有依赖参数,所以才会报错。
解决方案
1. 把函数封装成Nest服务(最推荐)
把你的test函数放到一个被Nest管理的Service里,这样就能继续用依赖注入,不用手动处理实例化:
第一步:创建LayoutsService
新建layouts.service.ts:
import { Injectable } from '@nestjs/common'; import { ExampleService } from 'path/to/ExampleService'; @Injectable() export class LayoutsService { constructor(private readonly exampleService: ExampleService) {} async test() { this.exampleService.ping(true); } }
第二步:在模块里注册这个服务
修改telegram.module.ts,把LayoutsService加入提供者列表:
import {Module} from '@nestjs/common'; import {TelegrafModule} from 'nestjs-telegraf'; import {TelegramService} from './telegram.service'; import {ExampleModule} from 'path/to/ExampleModule'; import { LayoutsService } from './layouts.service'; // 导入新服务 @Module({ imports: [ TelegrafModule.forRootAsync({ useFactory: () => ({ token: settings.bots.token, middlewares: [sessionMiddleware], launchOptions: { webhook: { domain: settings.bots.domain, hookPath: '/telegram', } } }), }), ExampleModule.register() ], providers: [TelegramService, LayoutsService], // 添加到提供者 exports: [LayoutsService] // 如果其他模块要用到,就加这句导出 }) export class TelegramModule{}
之后你在任何Nest管理的类里,都可以通过构造函数注入LayoutsService来调用test方法。
2. 从Nest全局容器获取实例(适合特殊场景)
如果必须在普通函数里用,可以在应用启动时保存Nest的容器引用,然后从容器里拿ExampleService实例:
第一步:保存容器引用
修改main.ts:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; // 全局变量保存容器 export let nestContainer; async function bootstrap() { const app = await NestFactory.create(AppModule); nestContainer = app.getContainer(); await app.listen(3000); } bootstrap();
第二步:在普通函数里使用
修改layouts.telegraf.ts:
import { ExampleService } from 'path/to/ExampleService'; import { nestContainer } from './main'; export async function test() { // 从容器获取已创建的ExampleService实例 const exampleService = nestContainer.get(ExampleService); exampleService.ping(true); }
⚠️ 注意:这种方式会破坏依赖注入的解耦性,尽量少用,只适合实在没法封装成Service的场景。
3. 手动传入依赖(不推荐)
如果ExampleService的依赖很简单,你也可以手动创建它的依赖实例,再传给ExampleService:
import { ExampleService } from 'path/to/ExampleService'; // 导入ExampleService需要的依赖 import { SomeDependency } from 'path/to/SomeDependency'; // 手动创建依赖实例 const someDependency = new SomeDependency(); // 传入依赖创建ExampleService实例 const exampleService = new ExampleService(someDependency); export async function test() { exampleService.ping(true); }
这种方式耦合度极高,后续ExampleService的依赖变化时,你得手动修改所有实例化的地方,不推荐在Nest项目里用。
内容的提问来源于stack exchange,提问作者Micos
相关产品推荐
相关产品推荐

