NestJS 模塊

2023-09-07 21:51 更新

模塊是具有 @Module() 裝飾器的類。 @Module() 裝飾器提供了元數(shù)據(jù),Nest 用它來組織應(yīng)用程序結(jié)構(gòu)。

5

每個 Nest 應(yīng)用程序至少有一個模塊,即根模塊。根模塊是 Nest 開始安排應(yīng)用程序樹的地方。事實上,根模塊可能是應(yīng)用程序中唯一的模塊,特別是當(dāng)應(yīng)用程序很小時,但是對于大型程序來說這是沒有意義的。在大多數(shù)情況下,您將擁有多個模塊,每個模塊都有一組緊密相關(guān)的功能。

@module() 裝飾器接受一個描述模塊屬性的對象:

providers由 Nest 注入器實例化的提供者,并且可以至少在整個模塊中共享
controllers必須創(chuàng)建的一組控制器
imports導(dǎo)入模塊的列表,這些模塊導(dǎo)出了此模塊中所需提供者
exports由本模塊提供并應(yīng)在其他模塊中可用的提供者的子集。

默認情況下,該模塊封裝提供程序。這意味著無法注入既不是當(dāng)前模塊的直接組成部分,也不是從導(dǎo)入的模塊導(dǎo)出的提供程序。因此,您可以將從模塊導(dǎo)出的提供程序視為模塊的公共接口或API。

功能模塊

CatsController 和 CatsService 屬于同一個應(yīng)用程序域。 應(yīng)該考慮將它們移動到一個功能模塊下,即 CatsModule。

cats/cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

要使用 CLI 創(chuàng)建模塊,只需執(zhí)行 $ nest g module cats 命令。

我已經(jīng)創(chuàng)建了 cats.module.ts 文件,并把與這個模塊相關(guān)的所有東西都移到了 cats 目錄下。我們需要做的最后一件事是將這個模塊導(dǎo)入根模塊 (ApplicationModule)。

app.module.ts
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class ApplicationModule {}

現(xiàn)在 Nest 知道除了 ApplicationModule 之外,注冊 CatsModule 也是非常重要的。 這就是我們現(xiàn)在的目錄結(jié)構(gòu):

src
├──cats
│    ├──dto
│    │   └──create-cat.dto.ts
│    ├──interfaces
│    │     └──cat.interface.ts
│    ├─cats.service.ts
│    ├─cats.controller.ts
│    └──cats.module.ts
├──app.module.ts
└──main.ts

共享模塊

在 Nest 中,默認情況下,模塊是單例,因此您可以輕松地在多個模塊之間共享同一個提供者實例。

6

實際上,每個模塊都是一個共享模塊。一旦創(chuàng)建就能被任意模塊重復(fù)使用。假設(shè)我們將在幾個模塊之間共享 CatsService 實例。 我們需要把 CatsService 放到 exports 數(shù)組中,如下所示:

cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService]
})
export class CatsModule {}

現(xiàn)在,每個導(dǎo)入 CatsModule 的模塊都可以訪問 CatsService ,并且它們將共享相同的 CatsService 實例。

模塊導(dǎo)出

模塊可以導(dǎo)出他們的內(nèi)部提供者。 而且,他們可以再導(dǎo)出自己導(dǎo)入的模塊。

@Module({
  imports: [CommonModule],
  exports: [CommonModule],
})
export class CoreModule {}

依賴注入

提供者也可以注入到模塊(類)中(例如,用于配置目的):

cats.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {
  constructor(private readonly catsService: CatsService) {}
}

但是,由于循環(huán)依賴關(guān)系,模塊類不能注入到提供者中。

全局模塊

如果你不得不在任何地方導(dǎo)入相同的模塊,那可能很煩人。在 Angular 中,提供者是在全局范圍內(nèi)注冊的。一旦定義,他們到處可用。另一方面,Nest 將提供者封裝在模塊范圍內(nèi)。您無法在其他地方使用模塊的提供者而不導(dǎo)入他們。但是有時候,你可能只想提供一組隨時可用的東西 - 例如:helper,數(shù)據(jù)庫連接等等。這就是為什么你能夠使模塊成為全局模塊。

import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Global()
@Module({
  controllers: [CatsController],
  providers: [CatsService],
  exports: [CatsService],
})
export class CatsModule {}

@Global 裝飾器使模塊成為全局作用域。 全局模塊應(yīng)該只注冊一次,最好由根或核心模塊注冊。 在上面的例子中,CatsService 組件將無處不在,而想要使用 CatsService 的模塊則不需要在 imports 數(shù)組中導(dǎo)入 CatsModule。

使一切全局化并不是一個好的解決方案。 全局模塊可用于減少必要模板文件的數(shù)量。 imports 數(shù)組仍然是使模塊 API 透明的最佳方式。

動態(tài)模塊

Nest 模塊系統(tǒng)包括一個稱為動態(tài)模塊的強大功能。此功能使您可以輕松創(chuàng)建可自定義的模塊,這些模塊可以動態(tài)注冊和配置提供程序。動態(tài)模塊在這里廣泛介紹。

以下是一個動態(tài)模塊定義的示例 DatabaseModule:

import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.provider';

@Module({
  providers: [Connection],
})
export class DatabaseModule {
  static forRoot(entities = [], options?): DynamicModule {
    const providers = createDatabaseProviders(options, entities);
    return {
      module: DatabaseModule,
      providers: providers,
      exports: providers,
    };
  }
}

forRoot() 可以同步或異步(Promise)返回動態(tài)模塊。

此模塊 Connection 默認情況下(在 @Module() 裝飾器元數(shù)據(jù)中)定義提供程序,但此外-根據(jù)傳遞給方法的 entities 和 options 對象 forRoot() -公開提供程序的集合,例如存儲庫。請注意,動態(tài)模塊返回的屬性擴展(而不是覆蓋)@Module() 裝飾器中定義的基本模塊元數(shù)據(jù)。這就是從模塊導(dǎo)出靜態(tài)聲明的 Connection 提供程序和動態(tài)生成的存儲庫提供程序的方式。

如果要在全局范圍內(nèi)注冊動態(tài)模塊,請將 global 屬性設(shè)置為 true。

{
  global: true,
  module: DatabaseModule,
  providers: providers,
  exports: providers,
}

如上所述,將所有內(nèi)容全局化不是一個好的設(shè)計決策。

所述 DatabaseModule 可以被導(dǎo)入,并且被配置以下列方式:

import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';

@Module({
  imports: [DatabaseModule.forRoot([User])],
})
export class AppModule {}

如果要依次重新導(dǎo)出動態(tài)模塊,則可以 forRoot() 在導(dǎo)出數(shù)組中省略方法調(diào)用:

import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';

@Module({
  imports: [DatabaseModule.forRoot([User])],
  exports: [DatabaseModule],
})
export class AppModule {}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號