如何在Angular前端结合GraphQL查询实现内存缓存?
Angular + Apollo Client 内存缓存实现方案
默认内存缓存启用
Apollo Client 内置InMemoryCache,无需额外配置即可实现基础缓存:首次查询后自动将结果存入内存,后续完全相同的查询(查询语句、变量一致)直接返回缓存数据,无需重复请求后端。
初始化配置示例
在Angular的GraphQL模块中确保实例化InMemoryCache:
import { NgModule } from '@angular/core'; import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular'; import { ApolloClientOptions, InMemoryCache } from '@apollo/client/core'; import { HttpLink } from 'apollo-angular/http'; export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> { return { link: httpLink.create({ uri: '/graphql' }), cache: new InMemoryCache(), // 启用默认内存缓存 }; } @NgModule({ exports: [ApolloModule], providers: [ { provide: APOLLO_OPTIONS, useFactory: createApollo, deps: [HttpLink], }, ], }) export class GraphQLModule {}
缓存读取策略控制
通过查询的fetchPolicy参数,可灵活控制缓存与请求的优先级:
cache-first(默认):优先读取缓存,缓存不存在时发起请求network-only:跳过缓存,强制发起请求获取最新数据cache-and-network:先返回缓存数据,同时后台发起请求更新缓存
查询策略示例
import { Apollo } from 'apollo-angular'; import gql from 'graphql-tag'; const GET_TARGET_DATA = gql` query GetTargetData($id: ID!) { targetData(id: $id) { id title detail } } `; // 首次查询缓存,后续直接读缓存 this.apollo.watchQuery({ query: GET_TARGET_DATA, variables: { id: '456' }, fetchPolicy: 'cache-first' // 可省略,默认即为该策略 }).valueChanges.subscribe(result => { this.targetData = result.data.targetData; });
数据更新时的缓存同步
当数据通过mutation更新后,可通过三种方式同步缓存:
1. 手动写入缓存
mutation执行完成后,调用cache.writeQuery覆盖指定查询的缓存数据:
const UPDATE_TARGET_DATA = gql` mutation UpdateTargetData($id: ID!, $detail: String!) { updateTargetData(id: $id, detail: $detail) { id detail } } `; this.apollo.mutate({ mutation: UPDATE_TARGET_DATA, variables: { id: '456', detail: '更新后的详情' }, }).subscribe(({ data }) => { // 更新对应查询的缓存 this.apollo.client.cache.writeQuery({ query: GET_TARGET_DATA, variables: { id: '456' }, data: { targetData: { ...this.targetData, detail: data.updateTargetData.detail } } }); });
2. 自动重新查询更新缓存
配置refetchQueries,让Apollo在mutation完成后自动重新执行指定查询,同步缓存:
this.apollo.mutate({ mutation: UPDATE_TARGET_DATA, variables: { id: '456', detail: '更新后的详情' }, refetchQueries: [ { query: GET_TARGET_DATA, variables: { id: '456' } } ] }).subscribe();
3. 列表数据的合并策略
针对列表类数据,可在InMemoryCache初始化时配置merge函数,避免更新时覆盖整个列表:
cache: new InMemoryCache({ typePolicies: { Query: { fields: { dataList: { merge(existing = [], incoming) { // 根据id去重合并新旧列表 const merged = [...existing]; incoming.forEach(item => { const index = merged.findIndex(i => i.id === item.id); if (index !== -1) merged[index] = item; else merged.push(item); }); return merged; } } } } } })
缓存失效与清除
- 清除指定查询的缓存:
this.apollo.client.cache.evict({ query: GET_TARGET_DATA, variables: { id: '456' } }); - 清除全部内存缓存:
this.apollo.client.cache.reset();
内容的提问来源于stack exchange,提问作者srimathi
相关产品推荐
相关产品推荐

