August 19, 2025
Reactive APIs in Angular Teil 2 – Resource API httpResource()
Click here for the english version of this blog post.
Reactive APIs in Angular 20: HTTP-Anfragen mit httpResource()
Die Resource API ermöglicht es, die Ergebnisse asynchroner Vorgänge als Signals bereitzustellen. In den meisten Anwendungen rufen Entwickler Daten über HTTP-Anfragen ab. Um diesen wichtigen Anwendungsfall zu vereinfachen, gibt es die Funktion httpResource()
, die wir uns in diesem Artikel genauer ansehen werden. Dies ist der zweite Teil unserer Reihe über die Resource API. Im ersten Teil haben wir die API allgemein und speziell die Funktionen resource()
und rxResource()
behandelt.
Wozu gibt es httpResource()?
Wie die anderen Resource-Methoden schließt auch httpResource()
die Lücke zwischen synchronen Signals und asynchronen Anfragen. Der besondere Vorteil von httpResource()
ist, dass es speziell dafür entwickelt wurde, HTTP-Anfragen zu vereinfachen und deren Ergebnisse als Signal zurückzugeben.
Da httpResource()
auf diesen speziellen Anwendungsfall zugeschnitten ist, ist es deutlich einfacher zu nutzen als resource()
oder rxResource()
. Vergleichen wir den notwendigen Code mit den Code-Beispiele aus Teil 1 und dem Stackblitz, um den Unterschied zu verdeutlichen.
resource()
Kurzer Rückblick: Für resource()
benötigen wir
- eine
params
Funktion, welche die Abhängigkeit der Resource von einem oder mehreren Signals definiert - ein
loader/stream
der eine asynchrone Operation durchführt, wenn sich die Anfrage ändert, und einen neuen Wert zurückgibt - ein
abortSignal
welches den Request abbricht, wenn eine neue Seite geladen werden soll, während eine andere am laden ist
1 2 3 4 5 6 7 8 9 10 11 12 |
page = signal(1); products = resource({ params: () => this.page(), loader: ({ params: page, abortSignal }) => fetch(`https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}`, { signal: abortSignal, }).then((res) => { if (!res.ok) throw new Error('Failed to fetch'); return res.json(); }), }); |
rxResource()
Bei rxResource()
können wir den HttpClient
verwenden und rxResource()
übernimmt für uns das Subscriben an das Observable aus dem stream
. Außerdem brauchen wir kein abortSignal
mehr, da auch das rxResource()
für uns übernimmt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private http = inject(HttpClient); page = signal(1); products = rxResource({ params: this.page, stream: ({ params: page }) => this.http .get<any>( `https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}` ) .pipe( map((response) => response.products), catchError((error) => { console.error('API error:', error); throw error; }) ), }); |
httpResource()
1 2 3 4 5 6 |
page = signal(1); products = httpResource<ProductsResponse>( () => `https://dummyjson.com/products?limit=10&skip=${(this.page() - 1) * 10}` ); |
Wie Du siehst, reduziert das httpResource()
-Beispiel den Boilerplate-Code erheblich und liefert dennoch dasselbe Ergebnis. Die httpResource()
-Funktion nutzt intern den HttpClient
, wodurch du alle seine Funktionen verwenden kannst. Du musst den HttpClient
nicht mehr explizit injizieren (wie bei rxResource()
) oder eine eigene fetch
-Logik implementieren (wie bei resource()
).
Zudem werden Anfragen, die sich wiederholen, automatisch abgebrochen, wenn dieselbe Anfrage während der Ladezeit erneut gesendet wird. Damit brauchen wir auch hier kein abortSignal
mehr und sparen Speicher und verhindern Inkonsistenzen im Anwendungszustand. Standardmäßig wird als Antwort JSON direkt geparst und zur Verfügung gestellt. Wie im HttpClient
kann man den Rückgabe-Typ jedoch anpassen.
Die httpResource()
bietet zudem die Möglichkeit komplexere Anfragen mit Request-Objekten zu erstellen. Dabei ist die Syntax ähnlich wie beim HttpClient
. Hier ein Beispiel, wie ein entsprechendes Request-Objekt aussehen könnte:
1 2 3 4 5 6 7 8 9 10 11 12 |
products = httpResource<ProductsResponse>(() => ({ url: `https://dummyjson.com/products`, method: 'GET', headers: { 'X-Special': 'true', }, params: { limit: '10', skip: String((this.page() - 1) * 10), fast: 'yes', } })); |
Du kannst hier den Endpoint, HTTP Methode, Custom Headers, Query Parameter und weiteres definieren. Weitere Informationen für komplexere Anfragen findest Du in der Angular Dokumentation.
Wann sollte die httpResource() verwendet werden?
Bestimmt frägst Du dich jetzt, ob man httpResource()
nicht immer verwenden sollte, wenn es doch so viel effizienter ist. Hier haben wir für Dich zusammengefasst, in welchen Anwendungsfällen Du die Resource API ideal nutzt:
resource()
- Wenn Du die Javascript
fetch
-Methode verwenden willst - Wenn Du im
loader
mit Promises arbeiten willst - Nützlich für andere asynchrone Operationen ohne HTTP-Anfragen und Observables
rxResource()
- Wenn Du im
stream
mit Observables arbeiten willst - Wenn Du RxJs benutzen willst (bspw. für
pipe()
) - Empfehlenswert, wenn du zusätzliche Processing-Schritte hast
httpResource()
- Am einfachsten für HTTP-Anfragen
- Für komplexere Request-Objekte
Wichtiger Hinweis! Allgemein gilt für die Resource API, dass sie nicht für andere Anfragen als GET-Anfragen verwendet werden sollte. Dazu solltest Du besser den HttpClient
direkt verwenden. Zwar kann man httpResource()
abändern um POST-Anfragen zu stellen, aber die Best-Practices empfehlen dies nicht. Mehr dazu im ersten Teil.
Beispiel: httpResource()
Lass uns hier noch einmal genauer auf das Beispiel der httpResource()
aus dem oberen Vergleich eingehen.
Zunächst erstellen wir ein ProductsResponse
Interface. Zwar ist dieses Interface nicht zwingend notwendig, aber vereinfacht den Umgang mit httpResource()
etwas, da wir den Typ der Http Antwort direkt definiert haben.
1 2 3 4 5 6 7 8 9 10 |
interface ProductsResponse { products: Array<{ id: number; title: string; price: number; }>; total: number; skip: number; limit: number; } |
Jetzt müssen wir nur noch die passende URL an httpResource()
übergeben, und schon haben wir praktisch dieselbe Funktionalität wie bei resource()
und rxResource()
.
1 2 3 4 5 6 |
page = signal(1); products = httpResource<ProductsResponse>( () => `https://dummyjson.com/products?limit=10&skip=${(this.page() - 1) * 10}` ); |
Wenn sich das Signal ändert wird erneut ein neuer Request gestellt. httpResource()
verhält sich somit sehr ähnlich zu den anderen Resource API Methoden – bietet jedoch eine optimierte API.
Folgend das komplette Beispiel. Dieses ist natürlich auch Teil von unserem StackBlitz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
interface ProductsResponse { products: Array<{ id: number; title: string; price: number; }>; total: number; skip: number; limit: number; } @Component({ selector: 'app-httpresource', standalone: true, imports: [CommonModule], template: ` <button (click)="page.set(page() - 1)" [disabled]="page() === 1">Previous</button> Page: {{ page() }} <button (click)="page.set(page() + 1)">Next</button> <ul *ngIf="products.value()?.products as productList"> <li *ngFor="let product of productList"> {{ product.title }} ({{ product.price }} €) </li> </ul> `, }) export class HttpResourceComponent { page = signal(1); products = httpResource<ProductsResponse>( () => `https://dummyjson.com/products?limit=10&skip=${(this.page() - 1) * 10}` ); } |
Erfahrung ist der beste Lehrer: Hands-On für die Resource API
Bist Du bereit, die Theorie in die Praxis umzusetzen? Das Stackblitz enthält neben unserem Beispiel für die httpResource()
, auch die Code-Beispiele für resource()
und rxResource()
, damit Du alles zur Resource API an einem Ort ausprobieren kannst.
Mit welchen Themen geht es weiter?
Die Resource API hilft uns dabei asynchrone Vorgänge mit den reactiven Signals zu verknüpfen und ist damit sehr nützlich, um effizienter und effektiver zu programmieren.
Auch sehr nützlich ist die @let
Syntax aus ng18, diese wollen wir Dir im nächsten Artikel vorstellen. In der Zwischenzeit lohnt es sich auch immer einen Blick in unsere Blogreihe zu den Angular Signals zu werfen.