July 21, 2025
Reactive APIs in Angular Part 1 – Resource API resource() and rxResource()
Klicke hier, für die deutsche Version des Artikels.
Reactive APIs in Angular 20: Work asynchronously with Signals using the Resource API
With Angular 19, a reactive API was introduced as a new feature, the Resource API. Although the API is still considered an experimental feature in v20, you can already use it. If you want to know what the Resource API is, what problem it can solve, what you should and shouldn’t use it for, then you’ve come to the right place. This article is a part of the Angular Guides series, in which we explore many exciting topics relating to Angular. This guide gives you an overview of current topics, starting with: What are signals and what advantages do they bring?
We continue our journey through the signal-based features of Angular with an insight into the new functions of the Resource API. In this first part, we look at the basics of resource()
and rxResource()
. In the second part, we will experiment with the new httpResource()
, which can be used to facilitate HTTP requests and output them directly as a signal.
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 the new Resource API?
So far, signals in Angular have only focused on the synchronous data flow. Saving states, inputs, queries, etc. With the new Angular update, asynchronous operations are to be integrated into Signals. The first step in this direction is being tested with the Resource API. A resource is an asynchronous dependency that is integrated with Signals. You can imagine a resource as consisting of three parts:
- A
params
function, which defines the dependency of the resource on one or more signals. Here the resource automatically reloads whenthis.page()
changes
1params: () => this.page(), // Signal-based request(here: pagination) - A
loader/stream
that performs an asynchronous operation when the request changes and returns a new value. Together with the params function, the product data is therefore called up again each time the page number changes.
12345loader: ({ params: page }) =>fetch(`https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}`).then((res) => {return res.json(); // Returns product data}), - The resulting instance of the resource, which itself provides various signals, contains the value and the status of the resource. The value is communicated asynchronously, i.e. only as soon as it is available. The status of a resource can be
loading
,resolved
,errored
, or more.
1products = resource({ ... }); // Resource-Instance
You can try out the complete example in our StackBlitz project below. You can also find out more about the Resource API in the official Angular documentation.
resource() vs rxResource() vs httpResource()
The Resource API offers three methods. The three methods work in a similar way but have different use cases.
resource()
is the “basic” variant of the three methods and works with promises. You should use this method if you prefer Javascript fetch
to retrieve data.
rxResource()
is the “reactive” variant. It uses upper servables. You should use this method if you already work with RxJS or prefer RxJS. You can also use it if you want to pipe the result through upper servable operators. Since Angular’s HttpClient
is observable-based, rxResource()
is a good choice here.
httpResource()
is the simplest and most flexible variant. With simple syntax, you can make an HTTP request with URL and optional parameters and even define a request object. The second part of this article will also deal with httpResource()
in more detail.
What problem does the Resource API solve?
Previously, asynchronous data (e.g. HTTP requests) had to be processed in Angular via RxJS observables – including manual subscribe and unsubscribe. Zone.js
was responsible for updating the UI, which often led to performance problems with complex apps.
Signals made reactive state management much more efficient, but it lacked an elegant way to integrate asynchronous operations, such as API calls, directly into Signals. Developers had to use workarounds such as toSignals()
or manual promises, which was cumbersome and error-prone.
The Resource API closes the gap by providing asynchronous data directly as signals – without subscribe and zone.js
:
1 2 3 4 5 |
// Example: API-Request as Signal products = resource({ params: () => this.page(), loader: ({ params: page }) => fetch(`/api/products?page=${page}`) }); |
The Resource API also enables abortable requests – particularly useful for GET requests. If a user switches quickly between pages, outdated requests are automatically canceled.
The Resource API is useful if you want to receive asynchronous data. It helps to convert the data directly into a signal so that you can work with it immediately without a major workaround. Resource also allows you to interrupt requests. Resource allows an abortSignal
, with which you can quickly interrupt requests and process another request instead. If, for any reason, the user makes several requests in quick succession, for example by quickly pressing different buttons, Resource interrupts these requests and only forwards the most recent one. This makes the application more efficient. However, there is one thing to be aware of here: the fact that requests can be interrupted means that data could be lost if Resource is used with POST request operations.
You should therefore only use Resource for GET requests, i.e. to load data into Signals. You should not use Resource for POST requests to send data.
Example: resource()
Here is a part of our StackBlitz example. In this example, the DummyJson page is fetched and data is loaded from it. An object is passed to resource()
. The object has the params
and loader
function, as explained above, and also an abortSignal
.
1 2 3 4 |
loader: ({ params: page, abortSignal }) => fetch(`https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}`, { signal: abortSignal, }) |
TheabortSignal
aborts the request via an AbortController if a new page is to be loaded while another is loading. You can try this out yourself by opening the Network tab in the Inspector tools in the StackBlitz project and then pressing “Next” very quickly. Here you can see how the status “(canceled)” appears for requests. The abortSignal
is responsible for this. By interrupting the requests, fewer network resources are used, which can be quite useful for larger websites.
A resource also has other properties such as value
, status
, isLoading
, error
, etc. you can find more details here. In our example, the value of the retrieved json is queried via products.value()
.
1 |
ngIf="products.value()?.products as productList |
This creates the list with which the various values of the products from DummyJson are displayed.
Here is the complete code for the resource()
example. As already mentioned, you can also edit and experiment with this in the StackBlitz project. You can find more details on how to use resource()
in the documentation.
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 |
@Component({ selector: 'app-resource', 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 ResourceComponent { 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(); }), }); } |
Example: rxResource
This rxResource()
example is very similar to the previous one. Instead of resource()
, rxResource()
is now used, which allows the HttpClient
to be used quite easily. To do this, the HttpClient
is injected first.
1 |
private http = inject(HttpClient); |
In the loader
, which is called stream
for rxResource()
since Angular v20, a url is now called and an observable is returned.
1 |
stream: ({ params: page }) => this.http .get<any>( `https://dummyjson.com/products?limit=10&skip=${(page - 1) * 10}` ) |
rxResource()
subscribed and unsubscribes the observable automatically. Also different from resource()
: No abortSignal
is required, as rxResource()
also automatically aborts GET requests. You can also test this again by quickly pressing “Next” in the rxResource()
example in the StackBlitz project and checking what happens in the Network tab. Even without an abortSignal
, the status “(canceled)” is displayed here for the GET requests.
Since we are using RxJs, we also have access to the pipe()
function with rxResource()
, which allows us to transform the received data as usual with RxJS.
Here is the complete code for the rxResource()
part of the StackBlitz-project. And here too, of course, is the link to the documentation.
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 35 36 |
@Component({ selector: 'app-rxresource', standalone: true, imports: [CommonModule, HttpClientModule], 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() as productList"> <li *ngFor="let product of productList"> {{ product.title }} ({{ product.price }} €) </li> </ul> `, }) export class RxResourceComponent { 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; }) ), }); } |
Experience is the best teacher: Hands-on for the Resource API
Are you ready to put theory into practice? This interactive StackBlitz example contains the sample application presented, which takes up the basic concepts of Resource and contains the examples and functions presented.
What now?
As already announced, part 2 will focus on httpResource()
. We will show you the differences to resource()
and rxResource()
and how you can make the best use of httpResource()
.