Angular

Angular

Tutorial Angular: Servicios en Angular

Angular servicios: creación y uso. Aprende a crear y usar servicios en Angular con ejemplos prácticos y detallados.

Los servicios en Angular son clases que encapsulan la lógica y los datos específicos de una aplicación. Se utilizan para compartir información y funcionalidades entre componentes a través de la inyección de dependencias.

Creación de un servicio

Los servicios se crean una vez y se pueden inyectar en varios componentes, lo que promueve la reutilización del código y la separación de responsabilidades.

Para crear un servicio en Angular, primero se debe generar una clase TypeScript decorada con el decorador @Injectable(). Esto le permite a Angular saber que el servicio puede ser inyectado en otros componentes o servicios.

Comandos para crear un servicio

Usando Angular CLI:

ng generate service nombre-del-servicio

o la versión abreviada:

ng g s nombre-del-servicio

Para crear un servicio dentro de una carpeta específica:

ng generate service ruta/nombre-del-servicio

Estos comandos generarán automáticamente un archivo de servicio con la estructura básica y el decorador @Injectable().

A continuación se presenta un ejemplo de código que define un servicio llamado DataService:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private data: string[] = [];

  addData(item: string): void {
    this.data.push(item);
  }

  getData(): string[] {
    return this.data;
  }
}

En este ejemplo, el servicio DataService encapsula la lógica y el estado para agregar y recuperar datos.

La opción providedIn: 'root' dentro del decorador @Injectable() garantiza que Angular cree una única instancia del servicio a nivel de aplicación, lo que permite compartir los mismos datos y métodos entre múltiples componentes que lo utilicen.

En Angular, incluyendo las versiones más recientes, es técnicamente posible crear servicios sin el decorador @Injectable() en algunos casos. Sin embargo, se recomienda siempre usar @Injectable() como buena práctica, incluso si el servicio no tiene dependencias inicialmente. Esto mantiene la consistencia del código y facilita futuras modificaciones.

Inyección de dependencias

Una vez que el servicio ha sido definido, puede ser inyectado en componentes que lo requieran.

La inyección de dependencias es una práctica en la que se proporcionan instancias de clases necesarias en lugar de crearlas directamente.

Angular se encarga de crear una sola instancia del servicio y la comparte entre todos los componentes que lo soliciten.

A continuación, se muestra cómo se realiza la inyección del servicio DataService en un componente:

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-data',
  template: `
    <button (click)="addData()">Agregar Dato</button>
    <ul>
      <li *ngFor="let item of dataService.getData()">{{ item }}</li>
    </ul>
  `
})
export class DataComponent {
  constructor(private dataService: DataService) {}

  addData(): void {
    this.dataService.addData('Nuevo dato');
  }
}

En este ejemplo, la inyección de dependencias se logra a través del constructor del componente. Al interactuar con el servicio DataService, el componente administra los datos sin involucrarse en la implementación subyacente.

Inyección de dependencias en Angular 17+

En Angular 17+, la inyección de dependencias en componentes ha sido simplificada. Ahora puedes usar la sintaxis de inyección en el constructor de forma más concisa con inject():

import { Component, inject } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-data',
  standalone: true,
  imports: [NgFor],
  template: `
    <button (click)="addData()">Agregar Dato</button>
    <ul>
      <li *ngFor="let item of dataService.getData()">{{ item }}</li>
    </ul>
  `
})
export class DataComponent {
  dataService = inject(DataService);

  addData(): void {
    this.dataService.addData('Nuevo dato');
  }
}

Nota que este componente está definido como standalone, una característica introducida en versiones recientes de Angular que permite crear componentes sin necesidad de declararlos en un módulo.

Ámbito y ciclo de vida de un servicio

El ámbito y el ciclo de vida de un servicio en Angular están determinados por la propiedad providedIn en el objeto de metadatos del decorador @Injectable().

Esta propiedad indica dónde se proporciona el servicio y cómo se administran las instancias del servicio.

providedIn: 'root': Esta opción indica que el servicio se proporciona a nivel de la aplicación y se crea una única instancia (singleton) para toda la aplicación. Es la opción predeterminada y es recomendable para la mayoría de los servicios que requieren un estado compartido a nivel de la aplicación.

providedIn: 'any': Una nueva opción que crea una instancia separada del servicio para cada módulo lazy-loaded que lo inyecte.

providedIn: SomeModule: Esta opción indica que el servicio se proporciona en el nivel del módulo especificado (en este ejemplo, SomeModule). Angular crea una instancia única del servicio para cada módulo que lo requiera. Al utilizar esta opción, se debe importar y agregar el servicio a la lista de providers del módulo correspondiente.

Ejemplo de un servicio proporcionado a nivel de módulo

Supongamos que hay un servicio llamado AuthService que maneja la autenticación de usuarios en una aplicación.

Se busca que este servicio esté disponible solo para un módulo específico llamado AuthModule, y no para toda la aplicación.

Aquí está el ejemplo:

// auth.service.ts
import { Injectable } from '@angular/core';

@Injectable({
    providedIn: AuthModule // Se especifica la provisión dentro del módulo AuthModule
})
export class AuthService {
}
// auth.module.ts
import { NgModule } from '@angular/core';
import { AuthService } from './auth.service'; 

@NgModule({
    providers: [AuthService], // Se agrega el servicio al arreglo de proveedores del módulo
    // Otros metadatos y configuraciones del módulo
})
export class AuthModule { }

Para lograr que el servicio esté disponible para ser inyectado en otros componentes, se debe proporcionar un proveedor para el servicio. Esto se hace en el metadato providers del módulo raíz o de un módulo específico, como en este ejemplo.

Proporcionar el servicio en un componente

Se puede proporcionar un servicio a nivel de componente agregándolo a la lista de providers en el decorador @Component.

Esto creará una nueva instancia del servicio para cada instancia del componente.

import { Component } from '@angular/core';
import { UserService } from './user.service';

@Component({
selector: 'app-users',
templateUrl: './users.component.html',
providers: [UserService]
})
export class UsersComponent {

}

Para componentes standalone:

@Component({
  standalone: true,
  providers: [UserService]
})
export class UsersComponent {
  constructor(private userService: UserService) {}
}

Observables en servicios

Los Observables son una característica proveniente de la biblioteca RxJS (Reactive Extensions for JavaScript). Un Observable representa una fuente de valores, o eventos, que uno puede "observar". 

Los servicios en Angular a menudo se utilizan para recuperar, procesar y enviar datos. Cuando estos procesos son asincrónicos, como la recuperación de datos de una API, los Observables son una herramienta valiosa.

A continuación, se muestra un ejemplo sencillo de cómo se puede crear un servicio en Angular que utiliza Observables para recuperar datos de una API:

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private http = inject(HttpClient);
  private apiUrl = 'https://api.ejemplo.com/datos';

  obtenerDatos(): Observable<any> {
    return this.http.get(this.apiUrl);
  }
}

En este ejemplo, el servicio DataService utiliza el módulo HttpClient para hacer una solicitud GET a una API.

La función obtenerDatos() devuelve un Observable que emitirá los datos cuando estén disponibles.

Suscripción a Observables

Para "escuchar" o "observar" los valores que emite un Observable, es necesario "suscribirse" a él.

La suscripción se realiza utilizando el método subscribe() del Observable.

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-ejemplo',
  template: `
    <div *ngIf="datos">
      {{ datos }}
    </div>
  `
})
export class EjemploComponent implements OnInit {
  
  datos: any;

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService.obtenerDatos().subscribe({
      next: (data) => this.datos = data,
      error: (error) => console.error('Ocurrió un error:', error)
    });
  }
}

En el componente EjemploComponent, se suscribe al Observable devuelto por obtenerDatos(). Cuando los datos estén disponibles, se asignarán al miembro datos del componente.

En las últimas versiones de Angular se ha introducido una nueva sintaxis para trabajar con Observables en las plantillas, eliminando la necesidad de suscribirse manualmente en muchos casos

import { Component } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { DataService } from './data.service';

@Component({
  selector: 'app-ejemplo',
  standalone: true,
  imports: [AsyncPipe],
  template: `
    <div *ngIf="datos$ | async as datos">
      {{ datos }}
    </div>
  `
})
export class EjemploComponent {
  datos$ = this.dataService.obtenerDatos();

  constructor(private dataService: DataService) {}
}

En este ejemplo, se usa el pipe async en la plantilla para manejar la suscripción al Observable, lo que simplifica el código y evita la necesidad de gestionar manualmente la suscripción y la limpieza.

Certifícate en Angular con CertiDevs PLUS

Ejercicios de esta lección Servicios en Angular

Evalúa tus conocimientos de esta lección Servicios en Angular con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Signals en Angular

Angular
Puzzle

Guards funcionales

Angular
Test

Decodificar JWT en Angular

Angular
Test

Servicio con HttpClient

Angular
Código

Ciclo de vida de componentes en Angular

Angular
Test

Gestión de productos de Fake Store API

Angular
Proyecto

Data binding en Angular

Angular
Test

Routes sin módulos en Angular

Angular
Código

Router en Angular

Angular
Test

Instalación de Angular

Angular
Puzzle

Route Guards basados en interfaces

Angular
Código

La directiva @if en Angular

Angular
Puzzle

Formularios reactivos en Angular

Angular
Código

Servicios en Angular

Angular
Puzzle

Interceptor funcional

Angular
Test

Servicio con Array

Angular
Código

La directiva @for en Angular

Angular
Puzzle

Interceptores HTTP

Angular
Código

Componentes standalone true

Angular
Puzzle

Formularios con ngModel en Angular

Angular
Puzzle

Routes en Angular

Angular
Test

Comunicación entre componentes Angular

Angular
Test

Parámetros en rutas con ActivatedRoute

Angular
Test

CRUD de Restaurantes y Platos

Angular
Proyecto

Tablas en Angular Material

Angular
Puzzle

Formulario de registro de usuarios

Angular
Proyecto

Instalación y uso de NgBoostrap

Angular
Puzzle

Desarrollo de componentes Angular

Angular
Test

JWT en Angular

Angular
Código

Formularios reactivos en Angular

Angular
Puzzle

Formularios en Angular Material

Angular
Puzzle

Layout con Angular Material

Angular
Puzzle

Effects en Angular

Angular
Test

Data binding

Angular
Código

HttpClient en servicios de Angular

Angular
Puzzle

Desarrollo de módulos Angular

Angular
Puzzle

Comandos Angular CLI

Angular
Puzzle

Subir archivo en formularios

Angular
Test

La directiva routerLink en Angular

Angular
Test

Todas las lecciones de Angular

Accede a todas las lecciones de Angular y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Instalación Angular

Angular

Introducción Y Entorno

Comandos Angular Cli

Angular

Introducción Y Entorno

Desarrollo De Componentes Angular

Angular

Componentes

Data Binding En Angular

Angular

Componentes

Ciclo De Vida De Componentes En Angular

Angular

Componentes

Comunicación Entre Componentes Angular

Angular

Componentes

La Directiva @If En Angular

Angular

Componentes

La Directiva @For En Angular

Angular

Componentes

Componentes Standalone

Angular

Componentes

Desarrollo De Módulos Angular

Angular

Módulos

Routes En Angular

Angular

Enrutado Y Navegación

Router En Angular

Angular

Enrutado Y Navegación

La Directiva Routerlink En Angular

Angular

Enrutado Y Navegación

Parámetros En Rutas Con Activatedroute

Angular

Enrutado Y Navegación

Routes Sin Módulos En Angular

Angular

Enrutado Y Navegación

Servicios En Angular

Angular

Servicios E Inyección De Dependencias

Httpclient En Servicios De Angular

Angular

Servicios E Inyección De Dependencias

Formularios Con Ngmodel En Angular

Angular

Formularios

Formularios Reactivos En Angular

Angular

Formularios

Subir Archivo En Formularios

Angular

Formularios

Layout Con Angular Material

Angular

Integración Con Angular Material

Tablas En Angular Material

Angular

Integración Con Angular Material

Formularios En Angular Material

Angular

Integración Con Angular Material

Instalación Y Uso De Ngboostrap

Angular

Integración Con Bootstrap Css

Signals En Angular

Angular

Signals Y Reactividad

Effects En Angular

Angular

Signals Y Reactividad

Route Guards Basados En Interfaces

Angular

Autenticación Y Autorización

Guards Funcionales

Angular

Autenticación Y Autorización

Interceptores Http Basados En Interfaz

Angular

Autenticación Y Autorización

Interceptores Http Funcionales

Angular

Autenticación Y Autorización

Seguridad Jwt En Angular

Angular

Autenticación Y Autorización

Decodificar Tokens Jwt En Angular

Angular

Autenticación Y Autorización

Certificados de superación de Angular

Supera todos los ejercicios de programación del curso de Angular y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Aprender a crear servicios en Angular.
  2. Comprender el concepto de inyección de dependencias.
  3. Entender el ámbito y el ciclo de vida de un servicio.
  4. Conocer la configuración de proveedores de servicios.
  5. Familiarizarse con Observables en servicios.