S

super-dev — full-stack

@super-dev.app · Full-stack · ★ disponible para proyectos
12,8k suscriptores·47 vídeos·Activo desde 2017

Desarrollador full-stack .NET / Angular con perfil DevOps en Azure Cloud. También cómodo con Flutter + Firebase. Construyo productos, los despliego, los monitorizo.

Volver a los artículos
ANGULAR
ANGULAR

Cargar datos con resource() y httpResource()

Artículo 2 de 4 — Angular 21 en la práctica
Zoneless, signals, resource(), @defer, SignalStore — el frontend moderno, de verdad.

Cargar datos asíncronos fue durante mucho tiempo sinónimo de subscribe() manual, de gestión de estado a mano ( loading , error , data ) y de fugas de memoria cuando se olvidaba un unsubscribe . Desde Angular 21, resource() y httpResource() encapsulan todo eso en una primitiva reactiva construida sobre signals .

El modelo resource()

Un resource() une una petición reactiva a un loader asíncrono. Cuando un signal leído en params cambia, Angular relanza automáticamente el loader y cancela la petición en vuelo mediante un AbortSignal . El resultado es un objeto de signals: value() , error() , status() , más isLoading() .

TypeScript
1import { resource, signal } from '@angular/core';
2
3export class UserCard {
4 private readonly userId = signal(1);
5
6 protected readonly user = resource({
7 params: () => ({ id: this.userId() }),
8 loader: ({ params, abortSignal }) =>
9 fetch(`/api/users/${params.id}`, { abortSignal }).then((response) =>
10 response.json(),
11 ),
12 });
13
14 protected next(): void {
15 this.userId.update((id) => id + 1);
16 }
17}

Cambiar userId es suficiente: sin subscribe , sin takeUntilDestroyed . El resource recarga, expone isLoading() durante la llamada y cancela la petición anterior.

httpResource para llamadas REST

httpResource() es la variante diseñada para HttpClient : atraviesa los interceptores, gestiona el tipado de la respuesta y reacciona a los cambios de URL. Se le pasa una función que devuelve la URL (o un objeto de petición completo) derivada de signals.

TypeScript
1import { httpResource } from '@angular/common/http';
2import { signal } from '@angular/core';
3
4export class ArticleList {
5 protected readonly tag = signal<string | undefined>(undefined);
6
7 protected readonly articles = httpResource<Article[]>(() => ({
8 url: '/api/articles',
9 params: this.tag() ? { tag: this.tag() } : {},
10 }));
11}

En el template, se consumen los estados directamente, sin pipe async :

TypeScript
1@if (articles.isLoading()) {
2 <p>Cargando…</p>
3} @else if (articles.error()) {
4 <p>Error al cargar.</p>
5} @else {
6 @for (article of articles.value(); track article.id) {
7 <h3>{{ article.title }}</h3>
8 }
9}

Los estados y sus trampas

status() devuelve un valor entre idle , loading , reloading , resolved , error y local . Dos sutilezas merecen atención:

  • durante una recarga , value() conserva el dato anterior ( reloading ), lo que evita

una pantalla en blanco — práctico para un patrón stale-while-revalidate.

  • httpResource está pensado para lectura (GET). Para un POST/PUT, se sigue usando

HttpClient clásico: un resource se relanza en cuanto cambia su petición, lo que no tiene sentido para una mutación.

Por qué abandonar las suscripciones manuales

El código RxJS imperativo mezcla tres preocupaciones: disparar la llamada, mapear el flujo y limpiar. Con resource , la dependencia se vuelve declarativa — el loader se relanza porque un signal cambió, punto. Se eliminan los BehaviorSubject de paginación, los switchMap defensivos y los finalize para volver a poner loading en false . La documentación oficial detalla la API en la guía async con resource .

resource() no reemplaza RxJS: reemplaza la fontanería . Describes qué cargar y de qué depende; Angular se encarga del cuándo, de la cancelación y del estado. El componente vuelve a ser una simple lectura de signals.
super-dev — portfolio.app
// Continuar en ANGULAR
Un motor estilo DOOM en el navegador, con tres backends
11 min • 1,4k lecturas
Migrar una app Angular a zoneless + signals
8 min • 4,1k lecturas
@defer y el nuevo control flow: menos JS al arranque
6 min • 2,9k lecturas