Dev Notes Blog

Angular resource and rxResource API

9th February 2025
Angular
angular
resource-api
signals
Last updated:6th September 2025
3 Minutes
599 Words

Angular v19 introduces a powerful new API for handling asynchronous data: the resource and rxResource APIs. These new primitives integrate seamlessly with Angular’s signal-based reactivity model, making it easier to fetch, manage, and update data while keeping track of loading and error states.

Why Use the Resource API?

Before resource, developers often relied on HttpClient with Observables or Promises to manage async data. While this approach worked well, it required additional RxJS operators like switchMap to handle reactive changes effectively. The new resource API simplifies this by:

  • Automatically tracking dependent signals and reloading data when they change.
  • Handling request cancellation to prevent race conditions.
  • Providing built-in methods for local updates and manual refreshes.
  • Offering rxResource for developers who prefer working with Observables.

resource

1
import { resource, Signal } from '@angular/core';
2
import { Component, computed, effect, signal } from '@angular/core';
3
4
interface MissionLog {
5
id: number;
6
title: string;
7
description: string;
8
status: 'pending' | 'completed';
9
}
10
11
@Component({ selector: 'app-mission-log', templateUrl: './mission-log.component.html' })
12
export class MissionLogComponent {
13
missionId = signal(1);
14
15
missionResource = resource({
11 collapsed lines
16
request: this.missionId,
17
loader: ({ request: id }) => fetch(`https://api.spacedata.com/missions/${id}`).then((res) => res.json()),
18
});
19
20
loading = this.missionResource.isLoading;
21
error = this.missionResource.error;
22
23
nextMission() {
24
this.missionId.update((id) => id + 1);
25
}
26
}

Key Takeaways:

  • request: Tracks the missionId signal so the loader fetches new data when it changes.
  • loader: Defines how the mission data is fetched.
  • isLoading and error: Useful for UI updates.

Understanding Loaders

A loader is an asynchronous function that retrieves data when the request signal changes. Loaders receive an object with:

  • request: The computed value from the request function.
  • previous: The previous state of the resource, which includes the last known value and status.
  • abortSignal: A signal used to cancel previous requests to avoid race conditions.

Example of using abortSignal in the loader:

1
missionResource = resource({
2
request: this.missionId,
3
loader: ({ request: id, abortSignal }) =>
4
fetch(`https://api.spacedata.com/missions/${id}`, { signal: abortSignal }).then((res) => res.json()),
5
});

This ensures that if a new request is made before the previous one completes, the older request is aborted.

Resource Status

The resource API provides several status signals to help track the loading process:

  • Idle No valid request; loader hasn’t run yet.
  • Loading Loader is currently running.
  • Resolved Loader has successfully completed and returned a value.
  • Error An error occurred while fetching data.
  • Reloading A new request is in progress while keeping the last successful value.
  • Local The resource was updated locally via .set() or .update().

Reloading a Resource

The reload method allows you to manually re-fetch data from the loader without changing the request signal. This is useful when you want to refresh the data on demand, such as when a user clicks a refresh button. Calling reload() will re-trigger the loader while maintaining the last known successful value until the new data is fetched.

1
refreshMission() {
2
this.missionResource.reload();
3
}

Updating Mission Data Locally

Sometimes, you need to modify data without fetching from the server again. The resource API allows local updates:

1
completeMission() {
2
this.missionResource.update(mission => ({ ...mission, status: 'completed' }));
3
}

This marks the mission as completed locally, without making another API request.

rxResource

For developers who prefer Observables, rxResource provides a reactive approach using RxJS:

1
import { rxResource } from '@angular/core/rxjs-interop';
2
import { HttpClient } from '@angular/common/http';
3
import { inject, signal } from '@angular/core';
4
5
@Component({ selector: 'app-rx-mission-log', templateUrl: './rx-mission-log.component.html' })
6
export class RxMissionLogComponent {
7
http = inject(HttpClient);
8
limit = signal(5);
9
10
missionsResource = rxResource({
11
request: this.limit,
12
loader: (limit) => this.http.get<MissionLog[]>(`https://api.spacedata.com/missions?limit=${limit}`),
13
});
14
}

This integrates seamlessly with Angular’s existing HttpClient and RxJS ecosystem, automatically switching to the latest request when the limit changes.

Conclusion

The new resource and rxResource APIs are a game-changer for handling async data in Angular. They provide:

  • Simple, declarative syntax for fetching data.
  • Automatic request cancellation.
  • Built-in support for local updates.
  • A smooth transition for developers using RxJS.
Article title:Angular resource and rxResource API
Article author:Andrés Arias
Release time:9th February 2025