Iniezione di un servizio Nest.js da un modulo diverso

L’inserimento di un servizio da un modulo Nest.js diverso prevede alcuni passaggi per garantire l’inserimento delle dipendenze e l’organizzazione del modulo corrette. Utilizzando due moduli di esempio, scopri come funziona il processo di esportazione e importazione dei servizi.

Generazione di un progetto Nest.js

Per generare un progetto Nest.js, devi avere la CLI installata sul tuo dispositivo. In caso contrario, esegui questo comando per installarlo:

 npm install -g @nestjs/cli

Con la CLI Nest.js installata, esegui questo comando per generare un nuovo progetto Nest.js:

 nest new <project-name>

Puoi sostituire “” con qualsiasi nome tu scelga. L’esecuzione del comando precedente genererà un nuovo progetto Nest.js con il nome specificato.

La struttura attuale del tuo progetto dovrebbe assomigliare all’immagine seguente:

Per esercitarti nell’inserire un servizio da un modulo a un modulo diverso, genererai due moduli, module-a e module-b. Genererai anche i file di servizio e controller corrispondenti.

Esegui questo comando per generare module-a:

 nest generate module module-a

Ed esegui il comando equivalente per module-b:

 nest generate module module-b

Quindi esegui questo comando per generare i file del servizio e del controller per module-a:

 nest generate service module-a && nest generate controller module-a

Ed esegui il comando equivalente per module-b:

 nest generate service module-b && nest generate controller module-b

La directory del tuo progetto attuale dovrebbe assomigliare a questa, con le directory src/module-a e src/module-b:

Esportazione di un servizio dal modulo A

Per esportare il servizio module-a dal modulo module-a, devi elencarlo come un’esportazione nel file del modulo module-a (module-a.module.ts). Per impostazione predefinita, la CLI Nest.js non fornisce un array di esportazioni nel decoratore @Module, quindi il file del modulo generato sarà simile al seguente:

 
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 {}

Per rendere service-a (module-a.service.ts) accessibile ai moduli che importano module-a, crea un array di esportazioni nel decoratore @Module e aggiungilo ModuleAService.

Così:

 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 {}

Successivamente, a scopo di test, aggiungi una semplice funzione al tuo file di servizio module-a (module-a.service.ts):

 import { Injectable } from '@nestjs/common';

@Injectable()
export class ModuleAService {
  getHello(): string {
    return 'Hello from Module A!';
  }
}

Questa funzione restituisce una stringa di esempio. Per confermare che puoi importare correttamente questo servizio, chiamerai quella funzione dal modulo-b dopo aver inserito il servizio-a.

Importare un servizio nel modulo B

Per importare un modulo in un altro, devi elencarlo come importato nell’array imports del modulo ricevente. In questo caso, devi aggiungere module-a all’array imports del decoratore @Module di module-b.

Come in precedenza, la CLI Nest.js non genera automaticamente un array imports, quindi devi aggiungerlo manualmente.

Innanzitutto, importa il modulo genitore (module-a.module.ts) nel modulo ricevente (module-b.module.ts), crea l’array di importazione e aggiungi ModuleAModule all’array:

 
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 {}

Successivamente, apri il file module-b.service.ts e importa il decoratore Inject e ModuleAServerice rispettivamente da @nests/common e ../module-a/module-a.service:

 import { Injectable, Inject } from '@nestjs/common';
import { ModuleAService } from '../module-a/module-a.service';

Il decoratore Inject contrassegna il proprio parametro come destinazione per l’inserimento delle dipendenze.

Successivamente, nella classe ModuleBService, aggiungi il blocco di codice seguente:

 @Inject(ModuleAService)
  private readonly moduleAService: ModuleAService;

Il blocco di codice sopra fornisce al tuo ModuleBService l’accesso ai metodi disponibili nel tuo ModuleAService.

Puoi testare il servizio chiamando il metodo getHello di 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();
  }
}

Successivamente, apri il file module-b.controller.ts e sostituisci il codice generato con il blocco di codice seguente:

 
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();
  }
}

Il blocco di codice sopra imposta un gestore di route GET per la funzione getHello.

Infine, effettua una richiesta GET con curl to localhost:3000/module-b/hello. Il comando dovrebbe stampare “Ciao dal modulo A!” alla tua console.

Hai inserito con successo un servizio in un altro modulo. Ciò può rivelarsi utile quando crei API con Nest.js che hanno più moduli che devono chiamare i rispettivi metodi.

Vantaggi dell’iniezione tra moduli

Sebbene chiamare direttamente un servizio da un altro modulo possa sembrare più semplice all’inizio, a lungo termine può portare a un sistema più complesso, meno gestibile e meno scalabile.

Tuttavia, l’iniezione tra moduli promuove la modularità e la riusabilità del codice, facilitandone la manutenzione. Inoltre, centralizza le dipendenze, migliora la testabilità e supporta un’architettura scalabile e disaccoppiata.