
1. Introduction
In recent versions of Angular (v17+), the framework introduced a Resource API and a companion helper called httpResource. These abstractions are designed to simplify data fetching and state management in applications that use the signals architecture. Rather than manually managing subscriptions and storing loading or error states in components, resources provide a declarative, reactive way to fetch and cache data. This blog explores what resource and httpResource are, why they matter, how to use them, and when to choose one over the other. Throughout this article, you’ll see examples, code snippets and best practices to optimise your Angular applications for performance and developer experience.
2. Understanding resource
A resource in Angular is an object created with the resource() function. It encapsulates a potentially asynchronous dependency—such as data from a service, a computed value or another resource—and exposes it as a signal. Key characteristics include:
- Lazy evaluation: A resource is not computed until it’s first read. Once created, it caches its result and only recomputes when its dependencies change.
- Reactive updates: Because resources produce signals, they integrate seamlessly with Angular’s reactive change detection. When the underlying data changes, the signal updates automatically and the UI reacts.
- Error and pending states: Resources track three states:
pending(loading),errorandvalue. These allow the UI to display appropriate feedback to the user during data loading or error conditions. - Composition: Resources can depend on other signals or resources, enabling complex data flows to be expressed in a declarative, hierarchical manner.
Below is a basic example of creating a resource that wraps a promise:
import { resource, type Resource } from '@angular/core';
// Create a resource that fetches user data
const userResource: Resource<User> = resource(async (signal) => {
// simulate async fetch (e.g., call to a service)
const response = await fetch('/api/user', { signal });
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json() as Promise<User>;
});
// Read the resource in a component
@Component({
selector: 'app-user',
template: `
<ng-container [ngSwitch]="userResource.state()">
<p *ngSwitchCase="'pending'">Loading...</p>
<p *ngSwitchCase="'error'">Error loading user data.</p>
<pre *ngSwitchCase="'value'">{{ userResource.value() | json }}</pre>
</ng-container>
`
})
export class UserComponent {
userResource = userResource;
}
In this example, the resource encapsulates the async fetch and exposes a signal (userResource.value()) with built‑in awareness of loading and error states. The component template uses ngSwitch to handle the different states gracefully.
3. Understanding httpResource
While resource can wrap any asynchronous function, httpResource is a specialised helper built on top of Angular’s HttpClient. It automates common patterns when fetching data via HTTP and exposes the result as a signal along with status flags. Important features include:
- Built on
HttpClient: It sends HTTP requests using Angular’sHttpClientand returns a signal representing the response. - Response states: Like
resource, it providespending,errorandvaluestates so the UI can display spinners or error messages during the request lifecycle. - Automatic cancellation: If the component that uses the resource is destroyed, the underlying HTTP request is automatically cancelled, preventing memory leaks and unnecessary network traffic.
- Reactive parameters:
httpResourcecan depend on other signals or resources. When those dependencies change (e.g., search parameters),httpResourceautomatically reissues the HTTP request and updates the signal.
Here is an example of using httpResource to fetch a list of posts from an API:
import { httpResource } from '@angular/common/http';
import { signal } from '@angular/core';
import { type Post } from './types';
// Reactive query parameters as a signal
const page = signal(1);
const pageSize = signal(10);
const postsResource = httpResource<Post[]>(
// Provide dependencies: the signals page and pageSize
() => [page(), pageSize()],
// Loader function that uses HttpClient to fetch data
(deps, client) => {
const [p, size] = deps;
return client.get<Post[]>(`/api/posts?page=${p}&limit=${size}`);
},
);
@Component({
selector: 'app-posts',
template: `
<button (click)="page.set(page() - 1)" [disabled]="page() === 1">Previous</button>
<button (click)="page.set(page() + 1)">Next</button>
<ng-container [ngSwitch]="postsResource.state()">
<p *ngSwitchCase="'pending'">Loading posts...</p>
<p *ngSwitchCase="'error'">Error loading posts.</p>
<ul *ngSwitchCase="'value'">
<li *ngFor="let post of postsResource.value()">{{ post.title }}</li>
</ul>
</ng-container>
`
})
export class PostsComponent {
postsResource = postsResource;
page = page;
}
In this example, httpResource automatically reacts to changes in the page or pageSize signals and re-fetches data accordingly. The component remains declarative: there is no need to manually subscribe or unsubscribe from observables.
4. Key Differences and Best Practices
resource and httpResource both return signals and manage asynchronous state, but they serve different use cases. The following table compares the two:
| Aspect | resource | httpResource |
|---|---|---|
| Purpose | Generic wrapper for any asynchronous function, not tied to HTTP. | Specialised wrapper for HTTP calls built on top of HttpClient. |
| Signal states | Provides pending, error and value states | Same as resource but tied to HTTP response lifecycle |
| Automatic cancellation | Requires manual cancellation or explicit handling. | Cancels underlying HTTP request when no longer needed (e.g., component destroyed). |
| Cache / memoization | Caches results until dependencies change. | Caches response and refetches when dependencies (signals) change. |
| Use cases | Wrapping any asynchronous work (local computations, Web Workers, etc.). | Fetching data via REST or GraphQL APIs in a reactive way. |
Best practices:
- Use
resourcefor non‑HTTP asynchronous tasks. When the data is derived from internal state, computations or other resources,resourceis the right choice. - Use
httpResourcefor HTTP requests. It reduces boilerplate, automatically tracks loading/error states and cleanly integrates with signals. - Keep dependencies minimal and explicit. Always pass only the signals that drive the HTTP call. Too many dependencies can cause unnecessary re-fetching.
- Handle errors gracefully. The presence of
errorstate allows you to show friendly messages or retry buttons in your UI.
5. Example: Comparing resource and httpResource
To illustrate the differences, consider a case where we need to load user profile data and compute the user’s full name. First, we use httpResource to fetch the user. Then we use a regular resource to derive the full name from the user data:
import { httpResource } from '@angular/common/http';
import { resource } from '@angular/core';
import { type User } from './types';
// Fetch the user via httpResource
const userRes = httpResource<User>(
() => [], // no dependencies in this case
(_, client) => client.get<User>('/api/user'),
);
// Derive full name using resource
const fullNameRes = resource(() => {
const user = userRes.value(); // depends on userRes signal
return `${user.firstName} ${user.lastName}`;
});
@Component({
selector: 'app-profile',
template: `
<ng-container [ngSwitch]="userRes.state()">
<p *ngSwitchCase="'pending'">Loading profile...</p>
<p *ngSwitchCase="'error'">Error loading profile.</p>
<div *ngSwitchCase="'value'">
<p>Name: {{ fullNameRes.value() }}</p>
<p>Email: {{ userRes.value().email }}</p>
</div>
</ng-container>
`
})
export class ProfileComponent {
userRes = userRes;
fullNameRes = fullNameRes;
}
This pattern demonstrates how resources can compose: httpResource handles the HTTP call and automatically tracks its state, while resource derives additional computed data from the result. The UI remains declarative and resilient to asynchronous complexities.
6. Example Interview Question
Question: Explain the difference between resource and httpResource in Angular. If you need to fetch a list of products from a REST API and also compute their discounted prices, how would you design your resources?
Answer: resource is a generic wrapper for any asynchronous computation, whereas httpResource is specifically designed to wrap HTTP calls using HttpClient. Both return signals that track pending, error and value states. In a typical app:
- Use
httpResourceto fetch the list of products: provide any reactive parameters (e.g., category filters) as dependencies. Angular automatically issues the HTTP request when those dependencies change and returns the response as a signal. - Use a separate
resourceto compute the discounted prices. This resource will depend on the products signal returned byhttpResourceand compute a new array with discounted values. - In the template, use
ngSwitch(or the*ngIf/assyntax) to handle loading and error states for the HTTP resource, and display the computed discount list once the value is available.
Explanation: This design keeps concerns separate: httpResource handles network requests and state tracking, while resource handles local computations. Because both emit signals, Angular’s reactive change detection ensures the UI updates whenever the data or its dependencies change.
7. Conclusion
The introduction of the Resource API and httpResource has significantly improved developer ergonomics in modern Angular. By encapsulating asynchronous operations as signals, they eliminate boilerplate, handle cancellation and error states automatically, and promote declarative patterns. Use resource for any non‑HTTP asynchronous tasks and httpResource when dealing with external APIs. Together, they facilitate clean, reactive data flows that enhance application performance and maintainability.
8. References
Angular Documentation – Resource API and httpResource – describes how resources encapsulate asynchronous dependencies, track pending, error and value states and integrate with signals (retrieved from the Angular v19+ documentation, article on reactive data fetching).
MDN Web Docs – Script loading attributes – used here for general context about asynchronous execution and the importance of handling loading states in JavaScript.
JavaScript.info – Scripts: async, defer – explains how asynchronous loading affects program execution and the importance of not blocking the page.