在Apollo-Angular中何时使用watchQuery与query?二者逻辑及差异解析
Hey there! Let's break down the differences between watchQuery and query in Apollo-Angular—this is such a common question once you start building with GraphQL in Angular, so I’m glad you’re digging into the details.
Core Logic
Let’s start with the basics of what each method actually does:
query()
This is your one-time data fetch workhorse. When you call query(), it:
- Checks Apollo’s local cache first (using the default
cache-firstfetch policy) to see if the data already exists. - If the cache doesn’t have the data, it sends a single HTTP request to your GraphQL server.
- Returns an Observable that emits exactly one result (the data from cache or server) and then completes.
- No further updates—unless you explicitly call
query()again.
watchQuery()
This is your real-time, reactive data listener. It’s designed to keep your UI in sync with both the local cache and remote data. When you initialize watchQuery():
- Starts by fetching the initial data (again, checking cache first by default).
- Returns an Observable that keeps emitting new data whenever:
- The GraphQL server returns an updated response (e.g., if you use
pollIntervalto refresh periodically). - The local Apollo cache is modified by another operation (like a mutation or another query updating the same data).
- The GraphQL server returns an updated response (e.g., if you use
- The Observable stays active until you unsubscribe from it—so it’s always listening for changes.
Ideal Use Cases
Knowing when to pick which method will save you from unnecessary network calls or stale UI:
Use query() when:
- You need data once for a static view (e.g., loading a user’s profile page that doesn’t need to update unless the user refreshes).
- You’re fetching data as part of a one-time action (e.g., after submitting a form, you fetch the updated list once).
- You want minimal overhead—since it doesn’t maintain a persistent subscription, it’s lighter for non-reactive use cases.
Use watchQuery() when:
- Your UI needs to update automatically when data changes (e.g., a chat room showing new messages, a dashboard reflecting real-time metrics).
- Other parts of your app might modify the same data (e.g., if a mutation updates a product’s stock, you want the product list to refresh instantly).
- You need to implement features like infinite scroll or pagination where new data loads and adds to the existing dataset.
- You want to use Apollo’s built-in polling (via
pollIntervaloption) to regularly refresh data from the server.
Key Differences at a Glance
| Aspect | query() | watchQuery() |
|---|---|---|
| Data Emissions | Single emission, then completes | Continuous emissions on cache/server changes |
| Cache Interaction | Only checks cache once on initial call | Listens for cache updates indefinitely |
| Subscription Lifecycle | Observable completes after first emission | Observable stays active until unsubscribed |
| Overhead | Lightweight, no persistent subscription | Slightly heavier due to ongoing listening |
| Polling Support | No built-in polling | Supports pollInterval for periodic refreshes |
Quick Code Examples
Let’s see how these look in Angular:
query() Example
import { Apollo } from 'apollo-angular'; import gql from 'graphql-tag'; import { map } from 'rxjs/operators'; @Component({ template: '<div *ngIf="user$ | async as user">{{ user.name }}</div>' }) export class UserProfileComponent implements OnInit { user$: Observable<User>; constructor(private apollo: Apollo) {} ngOnInit() { this.user$ = this.apollo.query({ query: gql` query GetUser($id: ID!) { user(id: $id) { id name email } } `, variables: { id: 'user-123' } }).pipe( map(result => result.data.user) ); } }
This fetches the user once and displays it—no automatic updates.
watchQuery() Example
import { Apollo } from 'apollo-angular'; import gql from 'graphql-tag'; import { map, Subscription } from 'rxjs'; @Component({ template: '<div *ngFor="let msg of messages$ | async">{{ msg.content }}</div>' }) export class ChatComponent implements OnInit, OnDestroy { messages$: Observable<Message[]>; private subscription: Subscription; constructor(private apollo: Apollo) {} ngOnInit() { const watcher = this.apollo.watchQuery({ query: gql` query GetChatMessages($roomId: ID!) { chatMessages(roomId: $roomId) { id content sender } } `, variables: { roomId: 'chat-room-456' }, pollInterval: 3000 // Refresh from server every 3 seconds }); this.messages$ = watcher.valueChanges.pipe( map(result => result.data.chatMessages) ); // If not using async pipe, remember to unsubscribe! this.subscription = this.messages$.subscribe(); } ngOnDestroy() { this.subscription.unsubscribe(); } }
This will automatically update the message list whenever new messages are added to the cache (via mutation) or the server returns fresh data every 3 seconds.
内容的提问来源于stack exchange,提问作者yussenn




