DEV Community

Ricardo Chavarria
Ricardo Chavarria

Posted on

Resource API en Angular: La revolución declarativa de los datos asincrónicos

Reactividad Declarativa con resource(), rxResource() y httpResource() en Angular

Introducción: Un nuevo paradigma en la reactividad de Angular

Angular está viviendo una de sus transformaciones más importantes desde la introducción de Ivy. Con Angular v17 y especialmente v18/v19, el framework ha empezado a adoptar un enfoque mucho más declarativo y reactivo, alejándose del tradicional modelo basado en RxJS y async pipe como eje central de la reactividad.

Las nuevas APIs resource(), rxResource() y httpResource() son un ejemplo claro de este cambio. Diseñadas para manejar flujos asincrónicos de datos de forma declarativa, estas APIs permiten simplificar la lógica de datos en componentes, reducir boilerplate y aprovechar el nuevo sistema de signals de Angular.

Este artículo explora a fondo estas APIs, con ejemplos prácticos y comparaciones, para ayudarte a comprender cuándo, por qué y cómo usarlas de forma efectiva.

resource(): Reactividad declarativa con Promesas

La función resource() es la forma más sencilla de integrar flujos asincrónicos (basados en Promesas) dentro del sistema de signals de Angular.

Uso básico de resource()

import { signal, resource } from '@angular/core';

const userId = signal(42);

const userResource = resource({
  params: () => ({ id: userId() }),
  loader: async ({ params }) => {
    const res = await fetch(`/api/users/${params.id}`);
    return res.json();
  },
});
Enter fullscreen mode Exit fullscreen mode

Acceso a estados reactivos

const user = computed(() => userResource.value());
const loading = computed(() => userResource.status() === 'loading');
const error = computed(() => userResource.error());
Enter fullscreen mode Exit fullscreen mode

Esta declaración permite que Angular se encargue de manejar estados de carga, cancelación, errores y la reactividad sin necesidad de suscripciones o async pipe.

rxResource(): Flujos RxJS reactivos en el mundo de Signals

rxResource() permite envolver un Observable y convertirlo en una resource reactiva, combinando lo mejor de RxJS con el sistema de signals.

Ejemplo práctico con HttpClient

import { inject } from '@angular/core';
import { rxResource } from '@angular/core/rxjs-interop';
import { HttpClient } from '@angular/common/http';

const http = inject(HttpClient);
const searchTerm = signal('');

const searchResults = rxResource({
  params: () => searchTerm(),
  loader: (term) => http.get(`/api/search?q=${term}`),
});
Enter fullscreen mode Exit fullscreen mode

Ventajas de rxResource()

  • Compatible con servicios existentes que retornan observables
  • Cancelación automática cuando cambian los parámetros
  • Integración directa con operadores de RxJS

httpResource(): Declaración más simple para operaciones HTTP

Si estás usando HttpClient y necesitas una resource, httpResource() simplifica la sintaxis eliminando la necesidad de definir el loader manualmente.

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

const userId = signal(1);

const userResource = httpResource({
  params: () => ({ id: userId() }),
  url: ({ params }) => `/api/users/${params.id}`,
});
Enter fullscreen mode Exit fullscreen mode

Características clave

  • Usa internamente HttpClient
  • Incluye cancelación, manejo de errores y estados reactivos
  • Requiere menos configuración

Comparación de las tres APIs

Característica resource() rxResource() httpResource()
Fuente de datos Promesa Observable RxJS HttpClient
Estados (loading/error)
Cancelación automática
Integración RxJS Parcial Total Parcial
Sintaxis simplificada Media Media Alta
Ideal para Carga remota Streams continuos APIs REST simples

Casos de uso reales

Búsquedas reactivas

const query = signal('');

const results = resource({
  params: () => ({ q: query() }),
  loader: async ({ params }) => {
    return fetch(`/api/search?q=${params.q}`).then(res => res.json());
  }
});
Enter fullscreen mode Exit fullscreen mode

Paginación

const page = signal(1);
const pageSize = signal(10);

const paginatedData = rxResource({
  params: () => ({ page: page(), size: pageSize() }),
  loader: ({ page, size }) => http.get(`/api/data?page=${page}&size=${size}`),
});
Enter fullscreen mode Exit fullscreen mode

Formularios y edición

Puedes usar resource().refresh() tras guardar los cambios para volver a cargar la data desde el servidor.

const userResource = resource(...);

async function saveChanges(user: User) {
  await http.put(`/api/users/${user.id}`, user);
  userResource.refresh();
}
Enter fullscreen mode Exit fullscreen mode

Ventajas frente a enfoques tradicionales

  • Eliminan la necesidad de async pipe
  • No requieren subscribe() manual ni destrucción de observables
  • Simplifican la composición de lógica reactiva
  • Mejoran la legibilidad y mantenibilidad

Conclusión

Las APIs resource(), rxResource() y httpResource() representan un cambio fundamental hacia una arquitectura declarativa y basada en signals en Angular. Aunque aún están en fase experimental, su adopción ofrece una experiencia de desarrollo moderna, con menos boilerplate, mejor manejo de estado y cancelación automática de solicitudes.

Estas herramientas permiten a los desarrolladores escribir aplicaciones más limpias, predecibles y fácilmente testeables. A medida que Angular sigue evolucionando, adoptar este paradigma puede ofrecer ventajas competitivas y mayor escalabilidad en proyectos de mediano y largo plazo.

Top comments (0)