W Nest.js proces włączania usług z jednego modułu do drugiego wymaga precyzyjnych działań, aby zapewnić właściwe zarządzanie zależnościami i logiczną strukturę modułów. Na przykładzie dwóch modułów przedstawiamy krok po kroku, jak eksportować i importować usługi.
Tworzenie nowego projektu Nest.js
Zanim zaczniesz, upewnij się, że masz zainstalowany Nest.js CLI. Jeśli go nie posiadasz, użyj poniższego polecenia:
npm install -g @nestjs/cli
Po instalacji narzędzia CLI, stwórz nowy projekt Nest.js za pomocą komendy:
nest new <project-name>
Zastąp „<project-name>” wybraną przez ciebie nazwą. To polecenie utworzy nowy projekt Nest.js.
Struktura twojego projektu powinna wyglądać podobnie jak na poniższym obrazku:
Aby przećwiczyć mechanizm wstrzykiwania usługi między modułami, stworzymy dwa moduły – „module-a” i „module-b”. Wygenerujemy również dla nich pliki usług i kontrolerów.
Uruchom to polecenie, aby utworzyć moduł „module-a”:
nest generate module module-a
Teraz utwórz moduł „module-b” za pomocą analogicznego polecenia:
nest generate module module-b
Następnie, użyj tej komendy, aby utworzyć pliki usług i kontrolera dla modułu „module-a”:
nest generate service module-a && nest generate controller module-a
I powtórz ten sam krok dla modułu „module-b”:
nest generate service module-b && nest generate controller module-b
Aktualna struktura projektu powinna wyglądać następująco, z katalogami „src/module-a” i „src/module-b”:
Udostępnianie usługi z modułu A
Aby usługa z modułu „module-a” była dostępna dla innych modułów, należy ją uwzględnić w sekcji eksportu pliku modułu „module-a” (module-a.module.ts). Domyślnie, Nest.js CLI nie dodaje tablicy „exports” w dekoratorze „@Module”, więc wygenerowany plik będzie wyglądać tak:
import { Module } from '@nestjs/common';
import { ModuleAService } from './module-a.service';
import { ModuleAController } from './module-a.controller';@Module({
providers: [ModuleAService],
controllers: [ModuleAController],
})export class ModuleAModule {}
Aby umożliwić innym modułom korzystanie z usługi „module-a.service.ts”, musimy dodać tablicę „exports” do dekoratora „@Module” i umieścić w niej „ModuleAService”.
Tak to wygląda:
import { Module } from '@nestjs/common';
import { ModuleAService } from './module-a.service';
import { ModuleAController } from './module-a.controller';@Module({
providers: [ModuleAService],
controllers: [ModuleAController],
exports: [ModuleAService],
})export class ModuleAModule {}
Następnie, dla celów demonstracyjnych, dodajmy prostą funkcję do pliku usługi „module-a” (module-a.service.ts):
import { Injectable } from '@nestjs/common';@Injectable()
export class ModuleAService {
getHello(): string {
return 'Hello from Module A!';
}
}
Ta funkcja zwraca przykładowy tekst. Aby sprawdzić, czy import usługi działa poprawnie, wywołamy tę funkcję z modułu „module-b” po wstrzyknięciu usługi „module-a”.
Włączanie usługi w module B
Aby zaimportować moduł do innego modułu, musisz go dodać do sekcji „imports” w module docelowym. W naszym przypadku musimy dodać „module-a” do tablicy „imports” w dekoratorze „@Module” modułu „module-b”.
Podobnie jak poprzednio, Nest.js CLI nie tworzy automatycznie tablicy „imports”, więc trzeba ją dodać samodzielnie.
Najpierw zaimportuj moduł „module-a” (module-a.module.ts) do modułu docelowego (module-b.module.ts), utwórz tablicę „imports” i dodaj do niej „ModuleAModule”:
import { Module } from '@nestjs/common';
import { ModuleBController } from './module-b.controller';
import { ModuleBService } from './module-b.service';
import { ModuleAModule } from '../module-a/module-a.module';@Module({
imports: [ModuleAModule],
controllers: [ModuleBController],
providers: [ModuleBService],
})export class ModuleBModule {}
Następnie, otwórz plik „module-b.service.ts” i zaimportuj dekorator „Inject” oraz „ModuleAService” odpowiednio z „@nestjs/common” i „../module-a/module-a.service”:
import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from '../module-a/module-a.service';
Dekorator „Inject” oznacza parametr jako miejsce wstrzykiwania zależności.
Następnie, w klasie „ModuleBService”, dodaj poniższy blok kodu:
@Inject(ModuleAService)
private readonly moduleAService: ModuleAService;
Powyższy kod umożliwia dostęp do metod w „ModuleAService” wewnątrz „ModuleBService”.
Możesz teraz przetestować usługę, wywołując metodę „getHello” z „ModuleAService”.
import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from 'src/module-a/module-a.service';@Injectable()
export class ModuleBService {
@Inject(ModuleAService)
private readonly moduleAService: ModuleAService;getHello(): string {
return this.moduleAService.getHello();
}
}
Następnie, otwórz plik „module-b.controller.ts” i zastąp jego zawartość poniższym kodem:
import { Controller, Get } from '@nestjs/common';
import { ModuleBService } from './module-b.service';@Controller('module-b')
export class ModuleBController {
constructor(private readonly moduleBService: ModuleBService) {}@Get('/hello')
getHello(): string {
return this.moduleBService.getHello();
}
}
Powyższy fragment definiuje obsługę żądania GET dla ścieżki „/hello”.
Na koniec, wykonaj żądanie GET za pomocą „curl” na „localhost:3000/module-b/hello”. W odpowiedzi powinieneś zobaczyć na konsoli „Hello from Module A!”.
Gratulacje, udało Ci się wstrzyknąć usługę do innego modułu! Jest to przydatne podczas tworzenia rozbudowanych API w Nest.js, gdzie wiele modułów musi współdzielić i wywoływać metody.
Zalety wstrzykiwania między modułami
Choć bezpośrednie wywoływanie usług z innych modułów może wydawać się łatwiejsze na początku, w dłuższej perspektywie może prowadzić do bardziej skomplikowanego, trudniejszego w utrzymaniu i mniej skalowalnego systemu.
Wstrzykiwanie między modułami promuje modułowość, ułatwia ponowne wykorzystanie kodu i jego konserwację. Ponadto centralizuje zależności, zwiększa testowalność oraz wspiera tworzenie architektury opartej na separacji warstw, co sprzyja skalowalności.