August 19, 2025
Reactive APIs in Angular Part 2 – Resource API httpResource()
Klicke hier, für die deutsche Version des Artikels.
Reactive APIs in Angular 20: HTTP requests with httpResource()
The Resource API allows the results of asynchronous operations to be provided as signals. In most applications, developers retrieve data via HTTP requests. To simplify this important use case, there is the httpResource()
function, which we will take a closer look at in this article. This is the second part of our series on the Resource API. In the first part, we covered the API in general and specifically the resource()
and rxResource()
functions.
If you want to learn more about the new Resource API and Angular in detail, visit one of our Angular courses:
- Angular Basic Training: https://www.thecodecampus.de/schulungen/angular
- Advanced Training: https://www.thecodecampus.de/schulungen/angular-advanced
What is httpResource() used for?
Like the other resource methods, httpResource()
bridges the gap between synchronous signals and asynchronous requests. The particular advantage of httpResource()
is that it was specifically designed to simplify HTTP requests and return their results as signals.
Since httpResource()
is tailored to this specific use case, it is much easier to use than resource()
or rxResource()
. Let’s compare the necessary code with the code examples from Part 1 and from the Stackblitz to illustrate the difference.
resource()
Quick recap: For resource()
, we need
- a
params
function that defines the dependency of the resource on one or more signals - a
loader/stream
that performs an asynchronous operation when the request changes and returns a new value - an
abortSignal
that cancels the request if a new page is to be loaded while another is still loading
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()
With rxResource()
, we can use HttpClient
, and rxResource()
takes care of subscribing to the observable from the stream
for us. We also no longer need an abortSignal
, as rxResource()
takes care of that for us as well.
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}` ); |
As you can see, the httpResource()
example significantly reduces boilerplate code while still delivering the same result. The httpResource()
function internally uses HttpClient
, allowing you to use all of its functions. You no longer need to explicitly inject HttpClient
(as with rxResource()
) or implement your own fetch
logic (as with resource()
).
In addition, repeated requests are automatically aborted if the same request is sent again during the loading time. This means that we no longer need an abortSignal
here either, saving memory and preventing inconsistencies in the application state. By default, JSON is parsed directly and made available as a response. However, as in HttpClient
, the return type can be customized.
The httpResource()
also offers the option of creating more complex requests with request objects. The syntax is similar to that of HttpClient
. Here is an example of what a corresponding request object might look like:
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', } })); |
Here you can define the endpoint, HTTP method, custom headers, query parameters, and more. For more information on more complex requests, see the Angular documentation.
When should httpResource() be used?
You’re probably wondering whether you should always use httpResource()
if it’s so much more efficient. Here we’ve summarized the use cases in which the Resource API is ideal for you:
resource()
- If you want to use the JavaScript
fetch
method - If you want to work with promises in the
loader
- Useful for other asynchronous operations without HTTP requests and observables
rxResource()
- If you want to work with observables in the
stream
- If you want to use RxJs (e.g. for
pipe()
) - Recommended if you have additional processing steps
httpResource()
- The simplest method for HTTP requests
- For more complex request objects
Important notice! As a general rule, the Resource API should not be used for requests other than GET requests. It is better to use HttpClient
directly for this purpose. Although it is possible to modify httpResource()
to make POST requests, best practices do not recommend this. More on this in the first part.
Example: httpResource()
Let’s take a closer look at the example of httpResource()
from the previous comparison.
First, we create a ProductsResponse
interface. Although this interface is not absolutely necessary, it simplifies the use of httpResource()
somewhat, as we have defined the type of the HTTP response directly.
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; } |
Now we just need to pass the appropriate URL to httpResource()
, and we have practically the same functionality as with resource()
and rxResource()
.
1 2 3 4 5 6 |
page = signal(1); products = httpResource<ProductsResponse>( () => `https://dummyjson.com/products?limit=10&skip=${(this.page() - 1) * 10}` ); |
When the signal changes, a new request is made. httpResource()
behaves very similarly to the other Resource API methods, but offers an optimized API.
Here is the complete example. This is, of course, also part of our 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}` ); } |
Experience is the best teacher: Hands-on for the Resource API
Are you ready to put theory into practice? In addition to our example for httpResource()
, the Stackblitz also contains code examples for resource()
and rxResource()
, so you can try out everything related to the Resource API in one place.
What are the next topics?
The Resource API helps us link asynchronous processes with reactive signals, making it very useful for more efficient and effective programming.
The @let
syntax from ng18 is also very useful, and we will introduce it to you in the next article. In the meantime, it is always worth taking a look at our blog series on Angular Signals.