NestJS官网文档阅读之工厂提供者 useFactory

基本概念

useFactory 是一种定义提供者的方法,它允许你通过一个工厂函数来动态地创建并返回服务的实例。 这个工厂函数可以注入其它的提供者,用于构建需要的服务实例。

工厂函数

工厂函数是一个普通的函数,它返回你想要提供的服务的实例。如果工厂函数需要其它依赖项来构造服务实例,你可以通过 inject 选项指定这些依赖项。

注入依赖项

当你的工厂函数需要依赖项时,你要在 inject 数组里列出这些依赖项的令牌(token)。NestJS 将解析这些令牌,然后将对应的服务实例作为参数传递给工厂函数。

可选依赖项

如果某个依赖项可能没有提供(可选的),你可以通过在 inject 数组中使用一个对象并设置 optional 属性为 true 来标记它。如果这个可选依赖项没有被提供,NestJS 将会传递 undefined 给工厂函数。

OptionsProvider 类

kotlin 复制代码
class OptionsProvider {
  get() {
    // 返回数据库连接选项
    return {
      host: 'localhost',
      port: 5432,
      // 可以有更多的连接配置选项
    };
  }
}

DatabaseConnection 类

javascript 复制代码
class DatabaseConnection {
  constructor(options) {
    // 使用选项创建数据库连接
    console.log(`Connecting to database at ${options.host}:${options.port}`);
    // 实际的连接代码会在这里
  }
}

在 AppModule 中,我们使用 useFactory 定义了一个 CONNECTION 提供者,它依赖于 OptionsProvider 和一个可选的 SomeOptionalProvider:

typescript 复制代码
const connectionProvider = {
  provide: 'CONNECTION',
  useFactory: (optionsProvider: OptionsProvider, optionalProvider?: string) => {
    const options = optionsProvider.get();
    console.log(`Optional provider value: ${optionalProvider}`);
    return new DatabaseConnection(options);
  },
  inject: [OptionsProvider, { token: 'SomeOptionalProvider', optional: true }],
};

@Module({
  providers: [
    connectionProvider,
    // 当你使用 `useFactory` 提供者并且工厂函数依赖于其他提供者时,你需要在模块的 `providers` 数组中包含所有的依赖提供者,此例子中为下面两个👇🏻
    OptionsProvider,
    // 下面这行目前被注释了,如果你开启它,它将提供一个值给 'SomeOptionalProvider'
    // { provide: 'SomeOptionalProvider', useValue: 'anything' },
  ],
})
export class AppModule {}
  • 当 NestJS 初始化 AppModule 时,它会解析 connectionProvider 的依赖项,并调用工厂函数来创建一个 DatabaseConnection 实例。

  • 如果你取消注释 { provide: 'SomeOptionalProvider', useValue: 'anything' },optionalProvider 将会有一个值(此例中为 'anything');如果保持注释,则 optionalProvider 参数将为 undefined。

通过这种方式,你可以根据情况的需要灵活地提供不同的实现,或者是根据环境的不同来决定如何创建你的服务实例。在上述例子中,通过使用 useFactory 方法,我们可以根据应用程序是否提供了 SomeOptionalProvider(通过 useValue 或其他方式)来决定工厂函数的行为。

如果应用程序提供了 SomeOptionalProvider,其值将被注入到工厂函数中,并可以用于进一步定制 DatabaseConnection 的创建过程或行为。如果没有提供 SomeOptionalProvider,工厂函数依旧可以正确执行,只不过没有额外的自定义配置。

这里的关键点是 inject 数组中的元素与工厂函数的参数顺序是对应的。NestJS 会解析 inject 数组中每个元素指定的令牌,并将解析得到的服务实例按照顺序作为参数传递给工厂函数。这就是为什么 useFactory 的能力非常强大,它可以让你根据不同的条件和依赖项来动态创建服务实例。

这种模式在需要根据不同环境或配置来创建不同服务实例时非常有用。例如,可能在开发环境中,你想连接到一个内存中的数据库,而在生产环境中,你想连接到一个真实的数据库服务器。使用 useFactory 提供者,你可以轻松地根据 NODE_ENV 环境变量或其他条件来动态选择不同的数据库连接实现。

这样灵活的设计允许你构建易于维护和扩展的应用程序,同时能够灵活应对不同的部署和运行环境。

相关推荐
tommyjiatong3 分钟前
资安底座连环雷:从 PHP2Shell 到 Node2Shell
node.js·php
SEO_juper3 小时前
Bash 交叉验证 robots.txt 和 sitemap:两个文件自相矛盾,页面永远收录不了
开发语言·python·node.js·json·bash
SEO_juper5 小时前
Go 站点地图生成器:从首页爬全站,一键生成 sitemap.xml
xml·开发语言·人工智能·golang·node.js·seo·外贸独立站
Moshow郑锴17 小时前
Ansible 批量部署 Node.js 服务:ZIP 直解与共享目录分发两种方案对比
node.js·ansible
少年的范儿1 天前
Windows 安装 Node.js 教程:nvm 版本管理 + pnpm 安装配置
windows·npm·node.js
peach1 天前
同样是装依赖,为什么 npm 长成 node_modules,Maven 长成 .m2
npm·node.js·maven
FungLeo1 天前
成为全栈·Go 后端篇·重写之前先锁基线:契约、Node 版本与行为清单
golang·node.js·go·openapi·契约测试·成为全栈
FungLeo2 天前
成为全栈·Go 后端篇·契约一致性与差分测试:两套实现如何互相校验
golang·node.js·go·合约测试·差分测试·成为全栈·api兼容
月夏2 天前
前端第一次接自己的后端:mock 切真接口踩了 2 个坑,组件只改了一行 import
前端·后端·node.js
SEO_juper2 天前
Node.js 页面主题聚焦度检测:title 和正文各说各的,AI 也读不懂
开发语言·人工智能·node.js·seo·外贸独立站