DEV Community

Arthur Groupp
Arthur Groupp

Posted on

Mastering Angular’s httpResource: Why Services Beat Components

Mastering Angular’s httpResource: Why Services Beat Components
Data fetching has always been a tricky balancing act in Angular:
Where should the logic live — inside the component or abstracted elsewhere?

With the introduction of httpResource in Angular 19, this question is more relevant than ever. httpResource provides a reactive, signal-driven way to work with HTTP calls — but if misused, it can quickly tangle business logic with UI code.

In this article, we’ll explore what httpResource does, the temptation of in-component usage, and why service-based abstraction is the key to maintainable, scalable applications.

Why httpResource Matters

At its core, httpResource is a reactive wrapper around Angular’s HttpClient.
Instead of manually subscribing to Observables, httpResource integrates seamlessly with the signals ecosystem — meaning its results can be consumed by computed, effect, linkedSignal, or directly in templates.

Some key properties:

  • Eager execution: Unlike HttpClient, which only fires on subscription, httpResource eagerly triggers requests when its reactive dependencies change.
  • Automatic cancellation: If dependencies change mid-request, the in-flight request is canceled and a new one is issued.
  • Full HttpClient support: Interceptors and all other features still apply.

Example of a simple reactive resource:

userId = input<string>();
user = httpResource(() => `/api/user/${userId()}`);
Enter fullscreen mode Exit fullscreen mode

Whenever userId changes, a fresh request is dispatched automatically.

The Temptation: Quick In-Component Usage

The most straightforward way to use httpResource is directly in a component:

@Component({ /* ... */ })
export class MyUserComponent {
  userId = input<string>();
  userResource = httpResource(() => `/api/user/${this.userId()}`);
}
Enter fullscreen mode Exit fullscreen mode

It works — but this convenience comes at a cost.

By mixing data-fetching logic into the component:

  • You violate single responsibility — components should focus on rendering and interaction, not on orchestrating HTTP calls.
  • Business logic becomes scattered and harder to reuse.
  • Testing gets messy: mocking component state and HTTP behavior together is more complex.

For tiny apps or prototypes, this pattern might be acceptable. However, in real-world applications, it creates tight coupling and long-term maintenance headaches.

The Better Way: Abstract httpResource into Services

A cleaner approach is to define httpResource inside dedicated services, not components.

This service-based pattern offers several advantages:

  • Separation of concerns: Components stay UI-focused while services handle data logic.
  • Reusability: Multiple components can consume the same resource logic.
  • Simpler testing: Service logic can be tested independently of UI behavior.
  • Consistency: Teams can share and maintain standardized resource definitions.

Example: Service-Based Resource

// user.service.ts
@Injectable()
export class UserService {
  // A shared resource for all consumers
  readonly usersResource = httpResource(() => `/api/users`);

  // Factory method for reactive user fetching
  createUserResource($userId: Signal<string>) {
    return httpResource(() => (
      $userId() ? `/api/user/${$userId()}` : undefined
    ));
  }
}

// user-details.component.ts
@Component({ /* ... */ })
export class UserDetailsComponent {
  readonly userId = input<string>();
  readonly #userService = inject(UserService);

  readonly userResource = this.#userService.createUserResource(this.userId);
}
Enter fullscreen mode Exit fullscreen mode

When Might In-Component Be Okay?

To keep this balanced:

  • Demos, prototypes, or playgrounds — quick feedback matters more than clean architecture.
  • Truly one-off fetches — where introducing a service would be unnecessary overhead.

But beyond these cases, service abstraction almost always pays off.

Conclusion: Future-Proof Your Angular Apps

Angular’s httpResource is a big step forward for reactive data fetching. But its power can become a liability if used naively inside components.

By moving your resource definitions into services, you get:

  • Cleaner components
  • Reusable data logic
  • Easier testing and scaling

👉 Next time you reach for httpResource, ask: “Should this live in a component — or does it belong in a service?”
Chances are, the service wins.

This simple shift will prepare your codebase for growth, teamwork, and the evolving Angular ecosystem.

Top comments (0)