Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • A angular
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Infrastructure Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • imunnic
  • angular
  • Wiki
  • Modulo 4

Last edited by imunnic Dec 22, 2025
Page history

Modulo 4

Bloque 4 – Servicios y comunicación con backend (Sesiones 15–19)

Este bloque introduce el uso de servicios en Angular como mecanismo principal para encapsular la lógica de negocio y la comunicación con un backend. Se trabaja con peticiones HTTP reales contra una API de gestión de recursos sanitarios y se profundiza en conceptos clave como Observables, manejo de errores y arquitectura escalable de servicios.

La API base utilizada en todos los ejemplos es:

http://localhost:8080/panacea

Las rutas concretas de los endpoints se obtienen desde un archivo de configuración centralizado.


Sesión 15 – Servicios en Angular

Qué es un servicio

Un servicio es una clase cuya responsabilidad principal es encapsular lógica que no pertenece directamente a la vista. Habitualmente se utilizan para acceder a datos remotos, compartir estado entre componentes o implementar reglas de negocio.

El uso de servicios favorece la reutilización de código y mantiene los componentes más simples y enfocados únicamente en la presentación.

Inyección de dependencias

Angular utiliza un sistema de inyección de dependencias que permite que los servicios se proporcionen automáticamente a los componentes u otros servicios que los necesiten. Esto reduce el acoplamiento y facilita el testeo.

Servicios singleton

Cuando un servicio se declara con providedIn: 'root', Angular crea una única instancia compartida en toda la aplicación. Este comportamiento es el más habitual para servicios de acceso a datos.

Creación de servicios

Ejemplo de servicio básico creado con CLI:

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

@Injectable({
  providedIn: 'root'
})
export class RecursosService {
  constructor() {}
}

Sesión 16 – HttpClient

Introducción

HttpClient es el servicio proporcionado por Angular para realizar peticiones HTTP. Está basado en Observables y permite tipar las respuestas, interceptar peticiones y manejar errores de forma centralizada.

En aplicaciones modernas con componentes standalone, se configura directamente en el bootstrap de la aplicación.

Configuración de HttpClient

import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    provideHttpClient()
  ]
});

Archivo de configuración de endpoints

{
  "apiBase": "http://localhost:8080/panacea",
  "recursos": "/recursos"
}
import config from '../config.json';

Peticiones GET y POST

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import config from '../config.json';
import { Observable } from 'rxjs';

export interface Recurso {
  id: number;
  nombre: string;
  tipo: string;
}

@Injectable({
  providedIn: 'root'
})
export class RecursosService {
  private baseUrl = config.apiBase + config.recursos;

  constructor(private http: HttpClient) {}

  obtenerRecursos(): Observable<Recurso[]> {
    return this.http.get<Recurso[]>(this.baseUrl);
  }

  crearRecurso(recurso: Partial<Recurso>): Observable<Recurso> {
    return this.http.post<Recurso>(this.baseUrl, recurso);
  }
}

Tipado de datos

El tipado de las respuestas permite detectar errores en tiempo de compilación y mejora la experiencia de desarrollo mediante autocompletado y validaciones.


Sesión 17 – Observables y RxJS

Qué es RxJS y por qué Angular lo usa

RxJS es una librería de programación reactiva basada en flujos de datos asíncronos. Angular la utiliza para gestionar eventos, peticiones HTTP y estados cambiantes de forma declarativa.

Observable vs Promise

Un Observable puede emitir múltiples valores a lo largo del tiempo y puede cancelarse. Una Promise solo se resuelve una vez y no es cancelable.

subscribe

this.recursosService.obtenerRecursos().subscribe({
  next: recursos => {
    this.recursos = recursos;
  },
  error: err => {
    console.error(err);
  }
});

Operadores básicos

import { map, tap, catchError } from 'rxjs/operators';
import { of } from 'rxjs';

obtenerRecursos() {
  return this.http.get<Recurso[]>(this.baseUrl).pipe(
    tap(() => console.log('Petición realizada')),
    map(recursos => recursos.filter(r => r.tipo === 'SANITARIO')),
    catchError(() => of([]))
  );
}

Sesión 18 – Manejo de errores y estados de carga

Introducción

Cuando se trabaja con datos remotos es fundamental gestionar correctamente los errores y los estados de carga para ofrecer una buena experiencia de usuario.

Interceptor de errores HTTP

Un interceptor permite capturar todas las peticiones HTTP y sus respuestas de forma centralizada.

import { HttpInterceptorFn } from '@angular/common/http';
import { catchError, throwError } from 'rxjs';

export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  return next(req).pipe(
    catchError(error => {
      console.error('Error HTTP', error);
      return throwError(() => error);
    })
  );
};

Configuración del interceptor:

import { provideHttpClient, withInterceptors } from '@angular/common/http';

provideHttpClient(
  withInterceptors([errorInterceptor])
);

Interceptor de autenticación (visión general)

Un interceptor de autenticación suele encargarse de añadir automáticamente un header Authorization con un token en cada petición saliente. Su lógica se centra en clonar la petición original y añadir el encabezado correspondiente.

Estados de carga

loading = false;

cargarRecursos() {
  this.loading = true;
  this.recursosService.obtenerRecursos().subscribe({
    next: data => this.recursos = data,
    error: () => this.loading = false,
    complete: () => this.loading = false
  });
}

Sesión 19 – Arquitectura de servicios

Separación de responsabilidades

Un servicio debe tener una única responsabilidad clara. La lógica de acceso a datos no debe mezclarse con lógica de presentación ni con reglas complejas de negocio.

Servicio genérico de acceso HTTP

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import config from '../config.json';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private apiBase = config.apiBase;

  constructor(private http: HttpClient) {}

  private buildUrl(params: Record<string, any>): string {
    let url = this.apiBase;
    Object.values(params).forEach(value => {
      url += `/${value}`;
    });
    return url;
  }

  get<T>(params: Record<string, any>): Observable<T> {
    return this.http.get<T>(this.buildUrl(params));
  }

  post<T>(params: Record<string, any>, body: any): Observable<T> {
    return this.http.post<T>(this.buildUrl(params), body);
  }

  patch<T>(params: Record<string, any>, body: any): Observable<T> {
    return this.http.patch<T>(this.buildUrl(params), body);
  }

  delete<T>(params: Record<string, any>): Observable<T> {
    return this.http.delete<T>(this.buildUrl(params));
  }
}

Uso desde un servicio de dominio

@Injectable({
  providedIn: 'root'
})
export class RecursosService {
  constructor(private api: ApiService) {}

  listar() {
    return this.api.get({ recursos: 'recursos' });
  }
}

Anti‑patrones comunes

  • Servicios excesivamente grandes y con múltiples responsabilidades.
  • Lógica HTTP directamente en los componentes.
  • Duplicación de llamadas a la API en distintos servicios.

Escalabilidad

Una arquitectura basada en servicios pequeños, bien definidos y apoyados en servicios genéricos facilita el mantenimiento y la evolución de la aplicación a largo plazo.

Clone repository

Índice

  • Inicio
  • Módulo 1. Fundamentos y arranque del proyecto
    • Módulo 1.1 Angular
    • Módulo 1.2 Estructura
    • Módulo 1.2 Arquitectura y conceptos base
  • Módulo 2. Componentes y reutilización
  • Módulo 3. Navegación y estructura de aplicación
  • Módulo 4. Servicios y comunicación con backend
  • Módulo 5. Gestión de estado (Stores)