I have got a NestJs app, that uses two services. The DbService that connects to the Db and the SlowService that does stuff rather slow and uses the injected DbService.
Now the app shall provide health routes outside of the api base path, so i need a different module that provides the controllers for the health routes.
I created a base module.
import { Module } from '@nestjs/common'
import { SlowService } from './slow.service'
import { DbService } from './db.service'
@Module({
imports: [],
controllers: [],
providers: [DbService, SlowService],
exports: [DbService, SlowService]
})
export class BaseModule {
}
The ApiModule and the HealthModule now both import the base module to be able to use the services.
imports: [BaseModule],
There is only a small problem. Both modules seem to construct their own instance of the service but I need it to be the same instance. I assume this, because the console.log from the constructor appear twice when starting the app. Am I missing a setting or something?
UPDATE
Here is my bootstrap method, so you can see how I initialize the modules.
async function bootstrap (): Promise<void> {
const server = express()
const api = await NestFactory.create(AppModule, server.application, { cors: true })
api.setGlobalPrefix('api/v1')
await api.init()
const options = new DocumentBuilder()
.setTitle('...')
.setLicense('MIT', 'https://opensource.org/licenses/MIT')
.build()
const document = SwaggerModule.createDocument(api, options)
server.use('/swaggerui', SwaggerUI.serve, SwaggerUI.setup(document))
server.use('/swagger', (req: express.Request, res: express.Response, next?: express.NextFunction) => res.send(document))
const health = await NestFactory.create(HealthModule, server.application, { cors: true })
health.setGlobalPrefix('health')
await health.init()
http.createServer(server).listen(Number.parseInt(process.env.PORT || '8080', 10))
}
const p = bootstrap()
NestJS Modules are Singletons by default. Their Providers are also singletons when they are provided from within the same module. However, there are cases where we want to use just a single solo class as a provider to a couple or more modules. In such cases, we can use the solo class as singleton or not.
A module is a class annotated with a @Module() decorator. The @Module() decorator provides metadata that Nest makes use of to organize the application structure. Each application has at least one module, a root module.
The forRoot sets up the loading of the . env file and the forChild uses it in another module. The problem is that forChild is called before forRoot . The ConfigService would be injected with missing config because forRoot hasn't executed first. > AppModule > ConfigModule.
Maybe you defined the services as providers for 2 modules. What you need to do is only define your BaseModule
as import in the module where you need it.
This example demonstrates the service OtherService
in OtherModule
which needs the DbService
from BaseModule
. If you run the example you will see that it only instantiates the DbService
once.
import {Injectable, Module} from '@nestjs/common';
import {NestFactory} from '@nestjs/core';
@Injectable()
export class SlowService {
constructor() {
console.log(`Created SlowService`);
}
}
@Injectable()
export class DbService {
constructor() {
console.log(`Created DbService`);
}
}
@Module({
imports: [],
providers: [SlowService, DbService],
exports: [SlowService, DbService]
})
export class BaseModule {}
@Injectable()
export class OtherService {
constructor(private service: DbService) {
console.log(`Created OtherService with dependency DbService`);
}
}
@Module({
imports: [BaseModule],
providers: [OtherService],
})
export class OtherModule {}
@Module({
imports: [
BaseModule,
OtherModule
],
})
export class AppModule {}
NestFactory.createApplicationContext(AppModule).then((app) => console.log('🥑 context created'));
This gist demonstrates BAD usage of providers, resulting in instantiating the DbService
twice: https://gist.github.com/martijnvdbrug/12faf0fe0e1fc512c2a73fba9f31ca53
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With