En esta página
HttpClient: consumir APIs REST
HttpClient en Angular
HttpClient es el servicio integrado de Angular para comunicarse con APIs REST. Devuelve Observables tipados y soporta interceptores, manejo de errores y transformaciones.
Configurar HttpClient
En app.config.ts, provee el cliente HTTP:
import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withFetch(), // Usa Fetch API nativa
withInterceptors([authInterceptor]),
),
],
};Métodos HTTP
HttpClient ofrece métodos para cada verbo HTTP:
const http = inject(HttpClient);
// GET - Obtener datos
http.get<Usuario[]>('/api/usuarios');
// POST - Crear recurso
http.post<Usuario>('/api/usuarios', { nombre: 'Ana' });
// PUT - Reemplazar recurso completo
http.put<Usuario>('/api/usuarios/1', datosCompletos);
// PATCH - Actualizar parcialmente
http.patch<Usuario>('/api/usuarios/1', { nombre: 'Ana Maria' });
// DELETE - Eliminar recurso
http.delete<void>('/api/usuarios/1');Parametros de consulta
Usa HttpParams para agregar query parameters:
import { HttpParams } from '@angular/common/http';
const params = new HttpParams()
.set('página', 1)
.set('limite', 20)
.set('orden', 'fecha');
http.get<Resultado>('/api/buscar', { params });
// GET /api/buscar?página=1&limite=20&orden=fechaHeaders personalizados
import { HttpHeaders } from '@angular/common/http';
const headers = new HttpHeaders()
.set('Authorization', `Bearer ${token}`)
.set('Accept-Language', 'es');
http.get('/api/datos', { headers });Interceptores funcionales
Los interceptores procesan TODAS las peticiones y respuestas HTTP:
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const auth = inject(AuthService);
const token = auth.token();
if (token) {
const reqConAuth = req.clone({
setHeaders: { Authorization: `Bearer ${token}` },
});
return next(reqConAuth);
}
return next(req);
};Registra interceptores en la configuración:
provideHttpClient(
withInterceptors([authInterceptor, loggingInterceptor]),
)Manejo de errores
Usa catchError de RxJS para manejar errores HTTP:
import { catchError } from 'rxjs/operators';
import { of, throwError } from 'rxjs';
obtenerUsuario(id: number) {
return this.http.get<Usuario>(`/api/usuarios/${id}`).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 404) {
return of(null); // Devolver null si no existe
}
return throwError(() => error); // Re-lanzar otros errores
}),
);
}HttpClient con resource
Puedes combinar HttpClient con rxResource para carga reactiva:
import { rxResource } from '@angular/core/rxjs-interop';
readonly usuarioId = signal(1);
readonly usuario = rxResource({
request: () => ({ id: this.usuarioId() }),
loader: ({ request }) =>
this.http.get<Usuario>(`/api/usuarios/${request.id}`),
});Buenas prácticas
- Tipar las respuestas — Siempre usa genericos:
get<MiTipo>() - Centralizar en servicios — No llames HttpClient desde componentes
- Manejar errores — Usa
catchErrorpara respuestas fallidas - Usar interceptores — Para autenticación, logging y retry
Práctica
- Crea un servicio CRUD: Implementa un servicio con metodos
obtenerTodos(),obtenerPorId(),crear()yeliminar()usandoHttpClientcontrahttps://jsonplaceholder.typicode.com/posts. Tipa todas las respuestas con genericos. - Agrega un interceptor de logging: Crea un interceptor funcional que registre en consola la URL y el metodo de cada peticion HTTP. Registralo con
withInterceptors()en la configuracion. - Maneja errores con catchError: En el metodo
obtenerPorId(), usacatchErrorpara devolvernullcuando el servidor responda con 404 y re-lanzar otros errores.
En la siguiente leccion aprenderemos los operadores esenciales de RxJS para transformar y combinar flujos de datos.
provideHttpClient
Registra HttpClient en app.config.ts con provideHttpClient(withFetch()). La opcion withFetch() usa la API Fetch nativa del navegador, más eficiente que XMLHttpRequest.
Suscripciones
HttpClient devuelve Observables frios que se completan automaticamente tras la respuesta. Pero en componentes, recuerda limpiar suscripciones de larga duracion con takeUntilDestroyed() o DestroyRef.
import { Injectable, inject, signal, computed } from '@angular/core';
import { HttpClient, HttpParams, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { of } from 'rxjs';
interface Articulo {
id: number;
título: string;
contenido: string;
autor: string;
fecha: string;
}
interface PaginaResponse {
datos: Articulo[];
total: number;
página: number;
}
@Injectable({ providedIn: 'root' })
export class ArticulosService {
private readonly http = inject(HttpClient);
private readonly baseUrl = '/api/articulos';
private readonly _cargando = signal(false);
readonly cargando = this._cargando.asReadonly();
obtenerTodos(página = 1, limite = 10) {
this._cargando.set(true);
const params = new HttpParams()
.set('página', página)
.set('limite', limite);
return this.http
.get<PaginaResponse>(this.baseUrl, { params })
.pipe(
tap(() => this._cargando.set(false)),
catchError((error: HttpErrorResponse) => {
this._cargando.set(false);
console.error('Error al cargar articulos:', error.message);
return of({ datos: [], total: 0, página: 1 });
}),
);
}
obtenerPorId(id: number) {
return this.http.get<Articulo>(`${this.baseUrl}/${id}`);
}
crear(articulo: Omit<Articulo, 'id'>) {
return this.http.post<Articulo>(this.baseUrl, articulo);
}
actualizar(id: number, cambios: Partial<Articulo>) {
return this.http.patch<Articulo>(
`${this.baseUrl}/${id}`,
cambios,
);
}
eliminar(id: number) {
return this.http.delete<void>(`${this.baseUrl}/${id}`);
}
}
Inicia sesión para guardar tu progreso