Skip to main content

Introduction

Overview

Fetching data in Apollo Orbit refers to the process of interacting with your GraphQL API. This encompasses several key operations:

  • Queries: Used to read data from your GraphQL server.
  • Mutations: Used to modify data on your GraphQL server and fetch the results.
  • Subscriptions: Used to get real-time data updates from your GraphQL server.
  • Fragments: Used to read specific pieces of data already present in the client cache.

Apollo Orbit provides dedicated methods for each of these operations, offering both RxJS Observable-based and Angular Signal-based approaches to handle the results reactively within your Angular application.

Methods

Apollo Orbit offers parallel APIs for data fetching, one based on RxJS Observables and the other leveraging Angular Signals. Choose the API that best fits your component architecture and reactivity model.

Observable MethodSignal MethodDescription
query-Executes a one-time query, ideal for route guards or resolvers.
watchQuerysignal.queryExecutes a query and watches the cache for updates. Ideal for reactive components.
mutatesignal.mutationExecutes a mutation to modify server data.
subscribesignal.subscriptionSubscribes to real-time updates from the server.
watchFragmentsignal.fragmentWatches a specific data fragment within the Apollo cache.
cache.watchQuerysignal.cacheQueryWatches data directly within the Apollo cache, without network requests. Ideal for local state.

Signals vs. Observables

With Angular v17+ establishing Signals as the primary reactive primitive, Apollo Orbit's dual API offers flexibility. Here's a guide to help you choose the right approach:

Signals (signal.query, signal.mutation, etc.) are ideal for:

  • Direct template binding: Using reactive state directly in templates, often eliminating the need for the async pipe.
  • Fine-grained reactivity: Allow Angular to efficiently track dependencies and update only the necessary parts of the DOM when signal values change.
  • Signal-driven variables: Use component signal inputs or component-defined signals to automatically trigger query updates when their values change.
  • Derived state: Easily creating computed values from your fetched data using computed().
  • Auto-cleanup: Reduced boiler plate code by removing the need for manual subscription management (like takeUntilDestroyed) often required with Observables.
  • OnPush and Zoneless: Seamlessly integrating with ChangeDetectionStrategy.OnPush and enabling the development of zoneless applications by leveraging Angular's built-in signal reactivity for change detection.

Observables (watchQuery, mutate, etc.) are ideal for:

  • Complex asynchronous operations: Utilising the extensive RxJS operator library for sophisticated stream manipulation, transformations, or coordination that go beyond simple component state binding.
  • Integration with RxJS-heavy Code: Interfacing with existing services, libraries, or parts of your application that heavily rely on RxJS patterns.
  • Specific Use Cases: Scenarios where the breadth of RxJS operators provides a distinct advantage for handling intricate asynchronous logic (e.g., managing multiple dependent streams, complex timing, custom error handling flows).

Recommendation

Start with the Signal-based API (signal.query, signal.mutation, etc.) as the default for handling reactive data in components.
Resort to the Observable-based API (watchQuery, mutate, etc.) when the specific power of RxJS operators is required for complex async flows or when integrating with existing Observable-based code.
Both APIs can effectively be used together within the same application.