I am currently utilizing nestjs and I am interested in creating an async provider. Below is my folder structure:
.
├── dist
│ └── main.js
├── libs
│ └── dma
│ ├── src
│ │ ├── client
│ │ │ ├── client.module.ts
│ │ │ ├── client.service.spec.ts
│ │ │ └── client.service.ts
│ │ ├── cmts
│ │ │ ├── cmts.module.ts
│ │ │ ├── cmts.service.spec.ts
│ │ │ └── cmts.service.ts
│ │ ├── dma.module.ts
│ │ └── index.ts
│ └── tsconfig.lib.json
├── nest-cli.json
├── package.json
├── package-lock.json
├── README.md
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
My intention is to designate the ClientService
as an async provider.
- I want the asynchronous operation of the database connection to execute first.
- After that, any dependent provider can begin invoking the sendSql() method.
Below are the files involved:
~/src/app.module.ts
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { DmaModule } from '@app/dma'
@Module({
imports: [DmaModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
~/src/app.service.ts
import { CmtsService } from '@app/dma/cmts/cmts.service'
import { Injectable } from '@nestjs/common'
@Injectable()
export class AppService {
constructor(private readonly cmtsService: CmtsService) {}
getHello(): string {
return 'Hello World!'
}
}
~/libs/dma/client/client.module.ts
import { Module } from '@nestjs/common'
import { ClientService } from './client.service'
@Module({
providers: [ClientService],
exports: [ClientService],
})
export class ClientModule {}
~/libs/dma/client/client.service.ts
import { Injectable } from '@nestjs/common'
@Injectable()
export class ClientService {
dbConnection: any;
async connectToDb(){
// connection logic...
this.dbConnection = theConnectionObject;
}
async sendSql(sql: string){
const result = await dbConnection.send(sql) // for example
return result
}
}
~/libs/dma/cmts/cmts.module.ts
import { Module } from '@nestjs/common'
import { CmtsService } from './cmts.service'
import { ClientModule } from '../client/client.module'
@Module({
imports: [ClientModule],
providers: [CmtsService],
exports: [CmtsService],
})
export class CmtsModule {}
~/libs/dma/cmts.service.ts
import { Injectable } from '@nestjs/common'
import { ClientService } from '../client/client.service'
@Injectable()
export class CmtsService {
constructor(private readonly clientService: ClientService) {}
}
The nestjs documentation mentions the following: here
It suggests this approach:
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const connection = await createConnection(options);
return connection;
},
}
However, I am concerned about whether it is advisable to directly create an instance from the provider:
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const clientService = new ClientService() // 👎 bad practice (?)
const connection = await clientService.connectDb();
return connection;
},
}