Menu
CoddyTech

Un servicio

Parte de la sección TypeScript y NestJS del Journey de Node.js de Coddy. Lección 9 de 24.

El controlador contiene las tareas, así que ninguna otra parte de la aplicación puede acceder a ellas. Los datos y la lógica pertenecen a un proveedor: una clase que Nest crea y entrega a quien la solicita.

@Injectable()
export class BooksService {
    private books = [{ title: 'Dune' }];
}

@Controller('books')
export class BooksController {
    constructor(private readonly booksService: BooksService) {}
}

@Injectable() marca la clase, y el módulo la incluye en providers. Una clase la solicita nombrándola en su constructor: esto es inyección de dependencias. private readonly delante del parámetro es una abreviatura de TypeScript: crea un campo this.booksService y almacena lo que Nest le pasa. Nest lee el tipo del parámetro, que el compilador conserva para las clases decoradas, crea una instancia para el módulo que la incluye y pasa esa misma instancia a todas las clases de ese módulo que la solicitan. Los datos se comparten, y una prueba puede pasar una instancia simulada en su lugar.

Esta lección comienza con el controlador ya llamando a this.tasksService.

challenge icon

Desafío

Fácil

Este paso abre el proyecto preparado del rastreador de tareas de Nest del curso, en lugar de los archivos de tu proyecto de Códigos de estado y errores (incluido src/tasks/tasks.controller.ts). Tu trabajo anterior permanece en su propia lección. Lee los archivos proporcionados antes de editar src/tasks/tasks.service.ts. Esta copia contiene las rutas de tareas de Nest, con el controlador preparado para delegar en un servicio.

Las tareas están dentro del controlador, así que ninguna otra parte de la aplicación puede acceder a ellas. Muévelas a un servicio: una clase que se encarga de las tareas, que Nest crea una vez y entrega a cada clase que lo solicita. El controlador ya se reescribió para llamar al servicio. Tu tarea es terminar el servicio y conectar ambos.

  1. En src/tasks/tasks.service.ts, marca la clase TasksService con @Injectable(), de @nestjs/common. Esto permite que Nest la cree y la entregue.
  2. En la misma clase, escribe un método create(title). Este crea una tarea con el siguiente id disponible (uno más que el id más grande de this.tasks), ese título y done: false. Añade la tarea a this.tasks y la devuelve. El controlador llama a este método desde POST /tasks, con el título del cuerpo de la solicitud.
  3. Escribe un método remove(id), donde id es un número. Si ninguna tarea tiene ese id, debe responder con 404, como findOne: primero llama a this.findOne(id), que lanza una excepción. Después, elimina la tarea de this.tasks. No devuelve nada.
  4. En src/tasks/tasks.module.ts, importa TasksService desde ./tasks.service; luego añade una lista providers al módulo, junto a controllers, e incluye TasksService en ella. Nest solo crea las clases que un módulo enumera allí.
  5. En src/tasks/tasks.controller.ts, reemplaza el comentario dentro de TasksController por un constructor que tome un parámetro, escrito private readonly tasksService: TasksService. Nest ve el tipo TasksService y pasa su único servicio. Las palabras private readonly delante de un parámetro también crean un campo, this.tasksService, que contiene lo que se pasó. Ese es el nombre que ya usan los métodos siguientes.

Pruébalo: envía POST { "title": "Buy milk" } a /tasks. Obtendrás 201 y:

{ "id": 4, "title": "Buy milk", "done": false }

Envía GET /tasks: cuatro tareas, con Buy milk al final. Envía DELETE /tasks/4: 204. Envía DELETE /tasks/99: 404 con "message": "Task 99 not found".

Pruébalo tú mismo

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

export interface Task {
    id: number;
    title: string;
    done: boolean;
    createdAt?: string;
}

// Haz que esta clase sea un proveedor que Nest pueda inyectar.
export class TasksService {
    private tasks: Task[] = [
        { id: 1, title: 'Write the README', done: true, createdAt: '2026-01-05T09:00:00.000Z' },
        { id: 2, title: 'Fix the login bug', done: false, createdAt: '2026-01-06T14:30:00.000Z' },
        { id: 3, title: 'Plan the sprint', done: false, createdAt: '2026-01-07T08:15:00.000Z' },
    ];

    findAll(done?: string): Task[] {
        if (done === undefined) {
            return this.tasks;
        }
        return this.tasks.filter((task) => task.done === (done === 'true'));
    }

    findOne(id: number): Task {
        const task = this.tasks.find((task) => task.id === id);
        if (!task) {
            throw new NotFoundException(`Task ${id} not found`);
        }
        return task;
    }

    // Escribe create(title) y remove(id) aquí.
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de TypeScript y NestJS

Practica por tu cuenta: Playground de Express