CodeForge

Angular 21 de Cero a Experto / Servicios y DI

Jerarquía de inyectores: dónde vive cada servicio

Teoría20 min20 XP

Hasta ahora todos tus servicios eran singletons globales (providedIn: 'root'). Pero a veces quieres lo contrario: una instancia FRESCA por cada componente —por ejemplo, un servicio de estado local a un formulario, o un "carrito" por cada pestaña—. Angular organiza los inyectores en una JERARQUÍA que hace esto posible y predecible. Entenderla te da control total sobre el alcance y el ciclo de vida de tus servicios.

Un árbol de despensas

Los niveles de la jerarquía

Instancia por componente: providers en @Component

Cuando pones un servicio en el array providers de un componente, Angular crea una instancia nueva para ESE componente (y sus hijos), independiente del resto de la app:

editor-gasto.component.ts
import { Component } from '@angular/core';
import { BorradorService } from './borrador.service';

@Component({
selector: 'app-editor-gasto',
providers: [BorradorService],   // ← una instancia NUEVA por cada <app-editor-gasto>
template: `...`,
})
export class EditorGastoComponent {
private borrador = inject(BorradorService);
// este BorradorService es SOLO de este editor: dos editores no comparten borrador
}

Compáralo con el singleton: providedIn: 'root' da UNA instancia para toda la app; providers: [X] en un componente da UNA instancia POR componente. La elección depende de si el estado es global (root) o local a una pieza reutilizable (componente).

comparacion.ts
// GLOBAL: la lista, el resumen y el form comparten los mismos gastos
@Injectable({ providedIn: 'root' })
export class BolsilloStore {}

// LOCAL: cada tarjeta editable tiene su propio borrador aislado
@Component({ providers: [BorradorService] })
export class TarjetaEditable {}

Cuándo usar cada uno

  • providedIn: 'root' — la mayoría de servicios: estado global, acceso a datos, lógica compartida, clientes HTTP. Es tu opción por defecto.
  • providers en un componente — cuando cada instancia del componente necesita su PROPIO estado aislado: un formulario complejo con estado de borrador, un widget que aparece varias veces y no debe compartir datos con sus hermanos.
  • providers en una ruta — estado que vive mientras estás en una sección de la app y se descarta al salir (lo verás en el módulo de routing).

Antes (providers en NgModule) vs Ahora (providedIn y providers standalone)

Pones `providers: [BorradorService]` en un componente que aparece 3 veces en la pantalla. ¿Cuántas instancias de BorradorService hay?

Mini-reto

Para cada caso, decide dónde proveerías el servicio (root, ruta o componente) y por qué:

  1. un AuthService con el usuario logueado; 2) un BorradorService que guarda lo que escribes en un formulario de gasto antes de enviarlo; 3) un ApiGastosService que llama al backend; 4) un WizardService que lleva el estado de un asistente de varios pasos que aparece en distintas pantallas.

Qué sigue

Ya controlas el ALCANCE de tus servicios. Falta un caso: ¿cómo inyectas algo que NO es una clase —una URL de configuración, un valor, una función—? Para eso están los tokens de inyección, el tema de la próxima lección, que cierra la teoría del módulo antes del reto.