您可以在 Angular / NestJS 模块提供程序中使用 `useFactory` 属性并返回一个类而不是实例吗?

Posted

技术标签:

【中文标题】您可以在 Angular / NestJS 模块提供程序中使用 `useFactory` 属性并返回一个类而不是实例吗?【英文标题】:Can you use the `useFactory` property in the Angular / NestJS Module Provider and return a Class instead of an instance? 【发布时间】:2021-04-30 04:20:17 【问题描述】:

我正在使用 NestJS 构建 API。我有一个到第 3 方 API 的网关服务,它将 HTTP 调用与数据处理逻辑分离。由于我不想在开发期间向 API 发出请求,因此我使用了一个工厂函数,该函数根据环境返回一个 Gateway 类——TinkMockGateway 或 TinkGateway。

在工厂函数中,我返回类而不是实例,它可以工作。这是令人惊讶的,因为我的实现不同于 Angular / NestJS 文档。在两个文档 [1, 2] 中,他们都说您必须返回要注入的类的实例——如果我们遵循工厂模式,这很有意义。

但是,当我使用下面的工厂函数(NestJS)时,依赖项会根据环境正确注入(网关)。

// other module providers...

  provide: TinkGateway,
  useFactory: () => environment.mockTinkGateway ? TinkMockGateway : TinkGateway,

框架是为我创建实例还是发生了什么?

【问题讨论】:

【参考方案1】:

不一样。

通过对 DI 使用 useFactory 方法,您必须返回一个实例。这就是工厂模式所说的,似乎这也是 Angular / NestJS 开发人员所期望的。

如果您使用 useFactory 然后返回一个类(而不是实例),您将在依赖于网关的类中获得该类。但是,您想要的是一个(可能共享的)实例。毕竟,这就是依赖注入的目的。看看下面两个console.dir 的例子:

    使用类(与您的问题中的代码相同):
// bank.repository.ts
//
// Adding a console.dir to see what's the output

@Injectable()
export class BankRepository implements IBankRepository 
  constructor(private tinkGateway: TinkGateway) 
    console.dir(tinkGateway);
  


// Output
>>> [Function: TinkGateway]
    使用实例:
// Adding the following provider in the module
// (substituting your previous provider).

// ...other providers

  provide: TinkGateway,
  useFactory: () =>
    environment.mockTinkGateway
      ? new TinkMockGateway()
      : new TinkGateway(),
  inject: [HttpService, ConfigService],
,
// more providers...

// Output
>>> TinkGateway 

【讨论】:

以上是关于您可以在 Angular / NestJS 模块提供程序中使用 `useFactory` 属性并返回一个类而不是实例吗?的主要内容,如果未能解决你的问题,请参考以下文章

带有nestjs的Angular-universal:错误:找不到模块'./drivers/node-mongodb-native/connection'

NestJS - 默认(通配符)路由?

Nestjs路由器中控制器如何拆分路由

部署在 NX monorepo 中创建的 nestjs 服务器

在firebase云函数中部署nestjs

如何在 NestJS 中设置类似 Angular 的配置环境文件?