NestJ在多个模块中使用同一服务实例

时间:2019-04-24 09:30:01

标签: nestjs

我有一个NestJs应用程序,它使用两项服务。连接到Db的DbService和执行缓慢的SlowService并使用注入的DbService。

现在,应用程序应在api基本路径之外提供运行状况路由,因此我需要一个不同的模块来为运行状况路由提供控制器。

我创建了一个基本模块。

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 {
}

ApiModule和HealthModule现在都导入了基本模块以能够使用服务。

  imports: [BaseModule],

只有一个小问题。这两个模块似乎都构造了它们自己的服务实例,但我需要它是同一实例。我以为是这样,因为启动应用程序时,构造函数中的console.log会出现两次。我是否缺少设置或其他内容?

更新

这是我的引导程序方法,因此您可以看到如何初始化模块。

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()

2 个答案:

答案 0 :(得分:1)

也许您将服务定义为2个模块的提供者。您只需要在需要的模块中将SELECT DISTINCT P.ProductId, PID.IndexId, PS.Status FROM Products AS P INNER JOIN #ProductIds AS PID ON P.ProductId = PID.ProductId INNER JOIN ProductStores AS PS ON P.ProductId = PS.ProductId ORDER BY CASE tb.Status WHEN 1 THEN 1 ELSE 2 END OFFSET (@PageIndex * @PageSize) ROWS FETCH NEXT (@PageSize) ROWS ONLY; 定义为导入即可。

此示例演示了BaseModule中的服务OtherService,它需要来自OtherModule的{​​{1}}。如果运行示例,您将看到它仅实例化DbService一次。

BaseModule

该要点演示了提供者的BAD使用情况,导致实例化DbService两次:https://gist.github.com/martijnvdbrug/12faf0fe0e1fc512c2a73fba9f31ca53

答案 1 :(得分:0)

我只是把它放在这里以防其他人需要它。

如果您真的希望应用中的每个模块共享同一个实例,那么您可能需要使用全局变量并将您的服务放入其中。

首先,在源应用的根目录(即 app.module)上定义您的服务。

nest g s shared-services/db

第二,在全局变量中提及您的服务。 (关注注释代码)

import { Injectable } from '@nestjs/common';

/* Define global variable as "any" so we don't get nasty error. */
declare var global: any;

@Injectable()
export class DbService {
  constructor() {
    console.log(`Created DbService`);

    /* Put the class inside global variable. */
    global.dbService = this;
  }
}

最后,您可以从其他控制器或服务调用您的服务。

import { Injectable } from '@nestjs/common';
import { DbService} from './../shared-services/db.service';

/* Define global variable as "any" so we don't get nasty error. */
declare var global: any;

@Injectable()
export class OtherService {

  /* Call the service. */
  protected readonly dbService: DbService = global.dbService;
  constructor() {
  }
} 

你可以走了。 我真的希望在未来 NestJs 具有与 Angular 相同的可注入功能,这样我们就不需要担心导出-导入任何服务了。