keepcalculator

06 Numbers and Powers

Angular 22 Stability & Resource APIs

Card No. 06·54044 · Updated · Standard formula, shown below

In Angular 22, the core framework and its resource APIs are stable, meaning you can use them in production without fear of breaking changes. The resource APIs, introduced as developer preview in earlier versions, let you manage asynchronous data loading with built-in caching, reactivity, and request cancellation, and in Angular 22 they are production-ready.

Background: From Developer Preview to Stable

Angular’s team has been steadily moving features out of “developer preview” status over recent releases. The resource APIs (including resource(), rxResource(), and the ResourceRef type) were first introduced in Angular 19 as experimental. After community feedback and API refinements in versions 20 and 21, Angular 22 marks them as stable. This means the API shape is locked, and future updates will focus on enhancements rather than breaking changes. For developers, this is a green light to adopt them in production applications.

How the Resource APIs Work

At their core, resource APIs provide a reactive wrapper around asynchronous operations like HTTP requests, database reads, or any Promise-based task. You define a loader function that returns a Promise or an Observable, and Angular handles the rest: it tracks the request status, caches the result, and automatically re-runs when dependencies change.

Here’s a simple example using resource():

const userResource = resource({
  request: () => ({ id: userId() }),
  loader: ({ request }) => fetchUser(request.id),
});

In this snippet, userId() is a signal. Whenever its value changes, Angular re-runs the loader with the new request object. The resource exposes signals for the value, error, and loading state:

  • userResource.value() – the resolved data (or undefined if not loaded)
  • userResource.error() – any error thrown by the loader
  • userResource.isLoading() – true while the loader is running
  • userResource.status() – a detailed status enum (Idle, Loading, Reloading, Resolved, Error, Local)

For Observable-based sources, rxResource() works similarly but takes an Observable as the loader return. Both integrate seamlessly with Angular’s change detection and signal-based reactivity.

Why Use Resource APIs Instead of Manual Subscriptions?

Before these APIs, you had to manually manage subscriptions, cancellation, and loading flags in each component. That led to repetitive boilerplate and subtle bugs when components unmounted before a request completed. The resource APIs centralize this logic:

  • Automatic cancellation: When a component is destroyed or the request changes, Angular cancels the in-flight request (for Observables, it unsubscribes).
  • Built-in caching: Results are cached by default, so re-visiting the same request doesn’t hit the server again unless you invalidate it.
  • Reactive dependencies: The loader re-runs automatically when any signal read inside request() changes.
  • Simpler state management: You get a single object that holds value, error, and loading state, reducing the need for multiple signals.

This pattern is especially useful in complex applications where data fetching is frequent and must be performant.

How to Choose Between resource() and rxResource()

The choice depends on your data source:

  • Use resource() when your loader returns a Promise (e.g., fetch, axios, a database call). It’s simpler and works with any async function.
  • Use rxResource() when you already have an Observable (e.g., Angular’s HttpClient returns Observables). It avoids converting to a Promise and preserves Observable features like retry and operators.

In practice, if you’re using Angular’s HttpClient, rxResource() is the natural fit. For other libraries that return Promises, resource() is cleaner.

Common Problems and Misconceptions

One frequent misunderstanding is that resources automatically deduplicate identical requests. They do not. If two components each create a resource with the same request, you get two separate HTTP calls. To share data across components, you need to define the resource at a shared parent level or use a service.

Another issue: forgetting that request() must return a new object when values change. If you return the same object reference, Angular may not detect a change. Always construct a fresh object inside request().

Also, be careful with error handling. If your loader throws, the resource sets error(), but it does not automatically retry. You must implement retry logic in the loader itself, or use rxResource() with RxJS retry operators.

Finally, don’t confuse resource() with Angular’s old HttpClient patterns. Resources are not a replacement for all HTTP logic; they are a state-management layer for async data.

Performance and Caching Considerations

Resources cache results in memory for the lifetime of the component. This is great for avoiding redundant requests, but it can become stale. You can manually invalidate the cache by calling resource.reload() or by changing the request. For time-sensitive data, consider adding a timestamp to the request object to force re-fetching.

Memory usage is minimal, but be aware that large data sets cached in resources will stay in memory until the component is destroyed. If you have huge datasets, you may want to clear the resource manually when leaving a view.

Another performance tip: use isLoading() to show spinners, but avoid showing the spinner on every keystroke if the request depends on user input. Debounce the request value using a signal that updates after a delay.

Comparison with Other Data Fetching Approaches

Angular developers historically used services with HttpClient and manual subscription management, or libraries like NgRx for global state. Resources sit in between:

  • vs. manual subscriptions: Resources are less verbose and handle cancellation automatically, but they are less flexible for complex chains of dependent requests.
  • vs. NgRx: NgRx provides a full global store with actions, reducers, and effects. Resources are local to a component or service and don’t enforce a global pattern. For simple data fetching, resources are overkill; for large applications with complex state, NgRx may still be better.
  • vs. TanStack Query (formerly React Query): That library offers similar features but is not Angular-native. Resources are built into Angular, so they have better integration with signals and change detection.

There is no one-size-fits-all; resources are a tool for a specific job, not a replacement for all state management.

Frequently Asked Questions

Is Angular 22 itself stable?

Yes, Angular 22 is a stable release. It follows the standard release schedule, and all features marked stable are production-ready. The resource APIs are part of that stable surface.

Can I use resource APIs with Angular’s HttpClient?

Yes, you can use rxResource() with HttpClient since it returns Observables. Alternatively, you can convert the Observable to a Promise with firstValueFrom() and use resource().

How do I share a resource across multiple components?

Define the resource in a shared service or a parent component, then inject it or pass it down as an input. This way, the resource is created once and reused.

Do resources work with Angular’s new control flow (@if, @for)?

Yes, resources work seamlessly with the new control flow. You can use @if (resource.value()) or @for (item of resource.value()) directly in templates.

What happens if the loader throws an error?

The error is captured in resource.error(), and the status becomes Error. You can display the error in the template and provide a retry button that calls resource.reload().

Are resources supported in Angular’s server-side rendering (SSR)?

Yes, resources work with SSR. During server-side rendering, the loader runs on the server, and the result is serialized and transferred to the client, avoiding a second request.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →