You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中参数未变更时如何避免重复获取数据

解决重复API调用的缓存方案

针对你遇到的同一storeName重复触发API请求的问题,这里提供两种RxJS+Angular的缓存实现方案,按需选择:

方案一:单实例缓存(仅缓存当前storeName数据)

适合当前场景下仅需复用最新同一storeName请求的情况,实现简单:

首先在服务类中添加两个私有变量,分别存储缓存的Observable和当前记录的storeName:

private cachedStore$: Observable<E2StoreFinderStore> | null = null;
private currentStoreName: string | undefined;

然后修改getStoreDetails函数:

public getStoreDetails(storeName?: string, origin?: string): Observable<E2StoreFinderStore> {
  // 检查参数未变且已有缓存,直接返回缓存数据
  if (storeName === this.currentStoreName && this.cachedStore$) {
    return this.cachedStore$;
  }

  this.currentStoreName = storeName;
  const api = this.OCC.getUrl(`/stores/details/name/${storeName}`);
  const params = new HttpParams()
    .append('fields', 'FULL')
    .append('type', 'POS');

  // 创建请求并通过shareReplay缓存结果,多组件订阅共享同一请求
  this.cachedStore$ = this.http.get<E2StoreFinderStore>(api, {
    responseType: 'json',
    params
  }).pipe(
    catchError(this.handleErrorService.handleError),
    shareReplay(1) // 缓存最新1条结果,供后续订阅复用
  );

  return this.cachedStore$;
}

核心逻辑:

  • 用currentStoreName判断传入参数是否与上次一致,一致则直接返回缓存
  • shareReplay(1)确保多个组件订阅时,只会发起一次API请求,后续订阅复用缓存的结果

方案二:多实例缓存(支持多个storeName的独立缓存)

如果后续可能需要调用不同storeName的接口,且希望每个storeName的结果都独立缓存,推荐用Map存储缓存:

在服务类中添加私有缓存Map:

private storeCache = new Map<string, Observable<E2StoreFinderStore>>();

修改getStoreDetails函数:

public getStoreDetails(storeName?: string, origin?: string): Observable<E2StoreFinderStore> {
  if (!storeName) {
    // 处理storeName为空的边界情况,可根据业务调整
    return throwError(() => new Error('storeName参数不能为空'));
  }

  // 检查缓存中是否已有该storeName的请求结果
  const cached$ = this.storeCache.get(storeName);
  if (cached$) {
    return cached$;
  }

  const api = this.OCC.getUrl(`/stores/details/name/${storeName}`);
  const params = new HttpParams()
    .append('fields', 'FULL')
    .append('type', 'POS');

  const request$ = this.http.get<E2StoreFinderStore>(api, {
    responseType: 'json',
    params
  }).pipe(
    catchError((error) => {
      // 请求失败时删除对应缓存,避免后续返回错误结果
      this.storeCache.delete(storeName);
      return this.handleErrorService.handleError(error);
    }),
    shareReplay(1)
  );

  // 将请求存入缓存Map
  this.storeCache.set(storeName, request$);
  return request$;
}

可选扩展:缓存失效与清理

如果需要缓存自动失效或手动清理,可以添加以下方法:

// 清除单个storeName的缓存
public clearStoreCache(storeName: string): void {
  this.storeCache.delete(storeName);
}

// 清除所有门店缓存
public clearAllStoreCache(): void {
  this.storeCache.clear();
}

// 若需自动失效,可修改shareReplay配置(例如30秒后缓存过期)
// shareReplay({ refCount: true, bufferSize: 1, windowTime: 30000 })

核心逻辑:

  • 用Map<string, Observable<...>>存储每个storeName对应的请求Observable
  • 请求失败时删除缓存,避免错误结果被复用
  • 支持多storeName的独立缓存,互不干扰

内容的提问来源于stack exchange,提问作者João Pedro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 00:15:30