Documentos de Académico
Documentos de Profesional
Documentos de Cultura
en aplicaciones Nest
A continuación vamos a hacer una zambullida completa en el mundo de los servicios de Nest,
que centralizan las operaciones para el acceso a los datos, así como implementan la lógica de
negocio. Los servicios son una de las clases tipo Provider que tenemos en NestJS, y como todo
provider son inyectables. Los servicios nos proveen de una capa que descarga de trabajo a los
controladores y a la vez permite reutilizar el código a lo largo de la aplicación. Veremos qué son
los servicios y luego implementaremos servicios y los usaremos desde los controladores.
Iremos ampliando la funcionalidad para proveer de más operaciones de trabajo con datos y
realizaremos el almacenamiento en distintos soportes, como la memoria o las bases de datos.
Servicios en NestJS
Qué son los servicios en Nest. Qué son los providers y cómo se puede inyectar estos tipos de
clase en los controladores. Implementaremos un servicio nuevo, crearemos algunos métodos,
para luego usarlo dentro de un controlador.
Los servicios son una pieza esencial de las aplicaciones realizadas con el framework NestJS.
Están pensados para proporcionar una capa de acceso a los datos que necesitan las
aplicaciones para funcionar. Mediante los servicios podemos liberar de código a los
controladores y conseguir desacoplar éstos de las tecnologías de almacenamiento de datos que
estemos utilizando.
Los servicios son clases, de programación orientada a objetos, como otros componentes de las
aplicaciones. Son clases clasificadas como "provider", un tipo especial de artefactos dentro del
framework. Por eso es interesante que expliquemos qué es un provider antes de ponernos a ver
código de servicios.
Los providers son un concepto que se usa en el framework Nest, para englobar a un conjunto
Los providers están preparados para ser inyectados en los controladores de la aplicación, y
otras clases si fuera necesario, a través del sistema de inyección de dependencias que
proporciona Nest. Gracias a la inyección de dependencias es muy sencillo crear y proporcionar
instancias de las clases a los controladores, delegando al propio Nest ese trabajo de instanciar
las clases.
Todos los providers que pensamos usar dentro de los módulos se tienen que declarar mediante
el decorador @Module(). Esto no es un problema porque generalmente esta tarea se realizará
automáticamente por el CLI al generar las clases inyectables. En este mismo artículo podrás
aprender a usar el CLI para realizar esta labor y experimentaremos cómo nos ayuda a la hora
de crear las clases tipo provider, en este caso servicios, y cómo el CLI las importa y declara
convenientemente en el módulo.
Pero antes de ponernos a crear nuevos servicios podemos fijarnos que en nuestra aplicación
inicial ya teníamos una declaración de providers en el módulo principal de la aplicación. La
podemos ver en el decorator @Module del archivo app.module.ts.
@Module({
imports: [],
controllers: [AppController, ProductsController],
providers: [AppService],
})
En esa declaración de "providers" tenemos un array donde encontramos el servicio usado para
el ejemplo del "Hola Mundo".
Servicios en Nest
Ahora que tenemos claro qué son los providers y sabemos que los servicios son clases incluidas
dentro del conjunto de providers, vamos a profundizar un poco en el concepto de servicio.
Construir un servicio
Para construir un servicio podemos usar el CLI de Nest. Para crear la clase de un servicio
lanzamos el siguiente comando:
Recuerda que el CLI tiene algunas abreviaciones que te pueden ahorrar teclear demasiado, de
modo que ese comando sería equivalente a escribir:
nest g s products
Una vez construido nuestro servicio con el comando anterior podemos apreciar que se crearon
los siguientes archivos:
Ambos archivos los situaron dentro de la carpeta src, como todo código propio de la
aplicación.
@Module({
imports: [],
controllers: [AppController, ProductsController],
providers: [AppService, ProductsService],
})
Igualmente a los controladores, si no queremos que se genere el archivo de los test unitarios
podemos escribir:
@Injectable()
export class ProductsService {}
Un detalle importante del sistema de inyección de dependencias para providers es que las
instancias proporcionadas a los controladores son únicas, es decir, existe una misma instancia
del servicio a lo largo de toda la aplicación.
Este hecho de crear una única instancia de una clase responde a un patrón conocido que
tiene el nombre de Singleton. Por tanto, podemos decir técnicamente que los servicios son
objetos Singleton.
Los servicios se envían a los controladores por inyección de dependencias. Para conseguirlo en
el controlador tenemos que hacer dos cosas:
En el proceso de inyección el propio constructor creará una propiedad dentro de la clase que
contendrá el servicio inyectado. Es decir, asociará el servicio al controlador.
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Patch, Post, Put, Res } from '@nestjs/common';
import { ProductsService } from './products.service';
@Controller('products')
export class ProductsController {
// …
}
Implementando el servicio
Ahora vamos a ver cómo sería el código para la implantación de un servicio. Vamos a ir poco a
poco, creando un código básico que nos permita hacer alguna cosa inicial, aunque luego, en
futuros artículos, iremos ampliando funcionalidad al servicio y permitiendo el uso de bases de
datos y similares.
Por tanto, en esta fase inicial del servicio vamos a usar la memoria como espacio de
almacenamiento, lo que no es muy práctico porque cada vez que se reinicie la aplicación
perderemos los datos.
@Injectable()
export class ProductsService {
private products = [
{
id: 1,
name: 'Vela aromática',
description: 'Esta vela lanza ricos olores',
},
{
id: 2,
name: 'Marco de fotos pequeño',
description: 'Marco ideal para tus fotos 10x15',
}
];
Hemos definido una variable privada llamada products. Además la hemos inicializado ya
con un array de dos objetos producto.
Hemos creado un método llamado getAll() que devuelve directamente el array de
productos.
Hemos creado un método llamado insert() que introduce un nuevo producto, recibido por
parámetro, en el array de productos.
Otro detalle importante, que destaca como carencia en este primer servicio sencillo es toda
la falta de lógica de negocio. Los servicios son el lugar ideal para realizar todas las
comprobaciones necesarias antes de realizar las operaciones. Por ejemplo, si me faltan tales
datos para hacer un alta, o si para hacer una modificación requiero tener un usuario con los
permisos adecuados. Poco a poco iremos complicando este código para incorporar este tipo
de comprobaciones necesarias.
Ahora, para cerrar finalmente el ciclo de esta primera aproximación a los servicios, veremos
cómo usamos este servicio desde el controlador. Básicamente lo que vamos a hacer es invocar
los métodos que nos proporciona el servicio, para implementar las operaciones de listado de
los productos y la inserción de nuevos productos.
@Controller('products')
export class ProductsController {
@Get()
getAllProducts() {
return this.productsService.getAll();
}
@Post()
@HttpCode(204)
createProduct(
Eso es todo, ahora puedes probar las rutas de get de todos los productos y del post para crear
un nuevo producto para ver cómo los datos de productos gestionado por el servicio van
aumentando.
Conclusión
En este artículo hemos realizado una bonita introducción de los servicios, componentes
fundamentales de las aplicaciones Nest. Los hemos ubicado dentro de las clases tipo
"providers", o proveedores, entendiendo las consecuencias derivadas, como poder hacer
inyectables estos servicios para un fácil uso dentro de los controladores.
Luego hemos realizado una implantación muy sencilla de un servicio y lo hemos usado dentro
del controlador, inyectándolo en el constructor y posteriormente usándolo en los métodos que
era necesario. Tenemos un API ultra-elemental, con persistencia en memoria, que tiene mucho
por delante para evolucionar, pero que empieza a parecerse a lo que nosotros queremos.
En el siguiente artículo vamos a abordar un tema interesante como es el de las interfaces, que
nos permitirán explorar algo más sobre las ventajas de TypeScript para el desarrollo de
aplicaciones en NestJS.