DEV Community

Cover image for Exploring Angular Resource API
Luis Castro
Luis Castro

Posted on

1

Exploring Angular Resource API

Introduction

It's been a while since my last article, but I couldn't pass up the opportunity to discuss this exciting new feature Angular is experimenting with.

Angular continuously introduces new features aimed at simplifying developer workflows and enhancing performance. One of its most promising experimental additions is the Resource API, designed specifically to streamline asynchronous data fetching with built-in reactivity. In this article, we'll break down this experimental feature and explore how it could fit into Angular applications.

But first, let's quickly understand why Angular is exploring this new approach.

📖 Why a New Resource API?

Currently, Angular developers rely heavily on Observables and the HttpClient for asynchronous operations. While powerful, Observables can introduce complexity, particularly in scenarios involving reactive updates, precise error handling, or efficient streaming.

The experimental Resource API aims to address these challenges by:

  • Providing a straightforward and intuitive API.
  • Facilitating reactive data fetching.
  • Including built-in status tracking (loading, error, success).
  • Improving performance through finer-grained reactivity.

It's essential to emphasize that this API is experimental and evolving. Certain key features like debouncing and mutations aren't fully implemented yet, as the initial focus is purely on data fetching.

Let's explore what's currently available.

🎯 Core Resource Interface

At the core of this API is the Resource interface, encapsulating reactive data fetching:

interface Resource<T> {
  readonly value: Signal<T>;
  readonly status: Signal<ResourceStatus>;
  readonly error: Signal<Error | undefined>;
  readonly isLoading: Signal<boolean>;
  hasValue(): boolean;
}
Enter fullscreen mode Exit fullscreen mode

Key points:

  • value: Holds reactive data as a Signal.
  • status: Indicates current state (Idle, Loading, Resolved, Error).
  • error: Captures any errors during fetch operations.
  • isLoading: Easy-to-use loading indicator.

This setup greatly simplifies handling async data in Angular templates.

🛠️ Creating Resources

Angular provides a straightforward resource function:

const userResource = resource({
  request: () => userId(),
  loader: async ({ value }) => fetchUser(value),
  defaultValue: null,
});
Enter fullscreen mode Exit fullscreen mode
  • request: Reactive input for fetching.
  • loader: Async function performing the fetch.
  • defaultValue: Initial placeholder value before the fetch completes.

You can easily track resource states in templates:

@if (userResource.isLoading()) {
  Loading...
  } @else if (userResource.hasValue()){
     {{ userResource.value().name }}
     } @else if (userResource.status() === ResourceStatus.Error) {
      Error: {{ userResource.error().message }}
  }
Enter fullscreen mode Exit fullscreen mode

🚀 Specialized HTTP Resources

Angular simplifies HTTP fetching further with httpResource:

const products = httpResource('/api/products');
Enter fullscreen mode Exit fullscreen mode

It integrates directly with Angular's existing HttpClient, supporting reactive patterns and automatically parsing JSON responses by default.

You can customize your requests:

const productDetail = httpResource({
  url: `/api/products/${productId()}`,
  method: 'GET',
  headers: { Authorization: 'Bearer token' },
});
Enter fullscreen mode Exit fullscreen mode

Additional Response Types

httpResource also supports different response formats:

  • ArrayBuffer: httpResource.arrayBuffer()
  • Blob: httpResource.blob()
  • Text: httpResource.text()

Example of fetching binary data:

const fileData = httpResource.arrayBuffer('/file.bin');
Enter fullscreen mode Exit fullscreen mode

🎛️ Advanced Features

Type Safety with Runtime Validation

For enhanced type safety, Angular’s Resource API integrates smoothly with runtime validation libraries like Zod:

const ProductSchema = zod.object({
  id: zod.number(),
  name: zod.string(),
});

const product = httpResource('/api/product', { parse: ProductSchema.parse });
Enter fullscreen mode Exit fullscreen mode

Resource Streaming

Resources can handle streaming responses:

const streamResource = resource({
  stream: async ({ value }) => fetchStreamedData(value),
});
Enter fullscreen mode Exit fullscreen mode

RxJS Integration

Existing Observables can easily integrate with rxResource:

const observableResource = rxResource({
  stream: param => observableService.getData(param),
});
Enter fullscreen mode Exit fullscreen mode

🌟 Status and Error Handling

Resources clearly distinguish between different loading states (initial load vs. reload):

enum ResourceStatus {
  Idle,
  Loading,
  Reloading,
  Resolved,
  Error,
  Local,
}
Enter fullscreen mode Exit fullscreen mode

Explicit state tracking simplifies error handling in templates:

@let resourceStatus = resource.status();
@let error = resource.error();
@if (resourceStatus === ResourceStatus.Loading) {
   Loading...
} @else if (resourceStatus === ResourceStatus.Resolved) {
  Data Loaded
} @else if (resourceStatus === ResourceStatus.Error) {
  Error: {{ error.message }}
}
Enter fullscreen mode Exit fullscreen mode

⚙️ Prefetching and Deferred Loading

Resources seamlessly integrate with deferred loading (@defer blocks), optimizing application performance:

<button #loadBtn>Load Data</button>

@defer (on interaction(loadBtn)) {
<data-cmp [data]="resource.value()"></data-cmp>
}
Enter fullscreen mode Exit fullscreen mode

Prefetching further improves performance:

@defer (prefetch on viewport(elementRef)) {
<component-cmp />
}
Enter fullscreen mode Exit fullscreen mode

📌 Migration and Limitations

This API is experimental, so please consider the following:

  • Observables integrate smoothly.
  • Structural directives remain compatible.
  • Essential features like mutations and debouncing aren't yet implemented.

Exercise caution when adopting experimental APIs, especially in production environments.

if you want to participate in the discussion or contribute to the development of this feature, you can join the Angular Resource API RFC. i alredy learn a lot from the discussion and i hope you can learn too.

🚦 Conclusion

Angular’s experimental Resource API presents an exciting new direction for async data management, addressing existing complexity and enhancing performance. While still evolving, it's definitely worth keeping an eye on.

Angular remains committed to improving the developer experience—making it easier to build better, faster applications. 🚀✨

Want to discuss this further or share your thoughts? Connect with me on Twitter, Threads, LinkedIn, or BlueSky. Let’s explore this together! 💻☕️

If you found this guide helpful, feel free to buy me a coffee. Your support means a lot! ☕️🙏

Tiugo image

Fast, Lean, and Fully Extensible

CKEditor 5 is built for developers who value flexibility and speed. Pick the features that matter, drop the ones that don’t and enjoy a high-performance WYSIWYG that fits into your workflow

Start now

Top comments (1)

Collapse
 
mihamulec profile image
Miha Mulec • Edited

Have you found any good/cool uses for @defer/prefetch in your apps? :) In our case most of our resources live on either a different route, or a dialog such as a few search components, so I have'nt explored it much except for obvious cases.

Btw we also use the parse function for type validation, but we wrap in a way which skips that check in prod. This way we get good errors if things change when developing, without the perf penalties :)

I still believe shared types, or a shared schema file for type gen, is better...but in our case & I assume many others that's simply not possible so validation through parse is the next best thing xD

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

👋 Kindness is contagious

If you found this post useful, consider leaving a ❤️ or a nice comment!

Got it