Wstrzykiwanie usługi Nest.js z innego modułu

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.