英文:
Why is my Nestjs Service being instantiated twice?
问题
我有以下的NgrokService
代码:
@Injectable()
export class NgrokService
implements OnApplicationBootstrap, OnApplicationShutdown
{
port: string
ngrokToken: string
ngrok: typeof import('ngrok') | null = null
constructor(private readonly configService: ConfigService) {
this.port = this.configService.get('API_PORT') ?? '3001'
this.ngrokToken = this.configService.getOrThrow('NGROK_TOKEN')
if (process.env.NODE_ENV === 'development') this.ngrok = require('ngrok')
}
async onApplicationBootstrap() {
if (process.env.NODE_ENV !== 'development') {
return
}
this.tunnelUrl = await this.ngrok!.connect({
addr: `https://localhost:${this.port}`,
subdomain: '<my_subdomain>',
region: 'us',
authtoken: this.ngrokToken,
})
}
async onApplicationShutdown() {
if (process.env.NODE_ENV !== 'development') {
return
}
this.ngrok!.disconnect()
}
}
我在这里使用它:
@Module({
imports: [],
controllers: [HealthController],
providers: [HealthService, AwsService, NgrokService],
})
export class HealthModule {}
还有在这里:
@Module({
imports: [
...
],
controllers: [...],
providers: [
...
NgrokService
],
})
export class AppModule {}
然而,不知何故,onApplicationBootstrap
钩子被调用了两次。经过调查,我只能通过将服务包装在一个模块中,创建一个全局锁变量来检查连接是否已经建立,才解决了这个问题。
我只想了解为什么会发生这种情况。为什么 Nestjs 会实例化服务两次?即使包装在模块中,服务也会被实例化两次。
英文:
I have the following NgrokService
here:
@Injectable()
export class NgrokService
implements OnApplicationBootstrap, OnApplicationShutdown
{
port: string
ngrokToken: string
ngrok: typeof import('ngrok') | null = null
constructor(private readonly configService: ConfigService) {
this.port = this.configService.get('API_PORT') ?? '3001'
this.ngrokToken = this.configService.getOrThrow('NGROK_TOKEN')
if (process.env.NODE_ENV === 'development') this.ngrok = require('ngrok')
}
async onApplicationBootstrap() {
if (process.env.NODE_ENV !== 'development') {
return
}
this.tunnelUrl = await this.ngrok!.connect({
addr: `https://localhost:${this.port}`,
subdomain: '<my_subdomain>',
region: 'us',
authtoken: this.ngrokToken,
})
}
async onApplicationShutdown() {
if (process.env.NODE_ENV !== 'development') {
return
}
this.ngrok!.disconnect()
}
}
I'm using it here:
@Module({
imports: [],
controllers: [HealthController],
providers: [HealthService, AwsService, NgrokService],
})
export class HealthModule {}
and also here:
@Module({
imports: [
...
],
controllers: [...],
providers: [
...
NgrokService
],
})
export class AppModule {}
For some reason though, the onApplicationBootstrap
hook gets called twice. After digging, I was only able to solve it by wrapping the service in a module and creating a global lock variable that checks if the connection was already made.
I just want to understand why this is happening. Why is Nestjs instantiating the service twice? Even wrapped in a module, the service gets instantiated twice.
答案1
得分: 4
提供者默认是每个模块的单例。
所以,如果你在多个模块中将 NgrokService
注册(即,在 providers
数组中),你将会得到多个实例。
英文:
providers are singleton by default per module
so if you have NgrokService
registered (ie, in the providers
array) in multiple modules, you'll get multiple instances.
答案2
得分: 0
如果你像这样做的话,也会遇到类似的行为:
```TypeScript
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, microserviceOptions);
await app.init();
其中app.init()
第二次调用了所有NestJS的初始化钩子。
<details>
<summary>英文:</summary>
Also, you could receive such behavior if you do something like that:
```TypeScript
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, microserviceOptions);
await app.init();
Where app.init()
secondly call all NestJS initializing hooks
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论