Angular中使用forkJoin发起API请求出现重复调用问题如何解决
问题根源
你遇到的重复请求问题确实来自fetchShopOrders的内部订阅:
- 缓存未命中时,你在构造完带
shareReplay的HTTP请求流后直接调用了subscribe,这会立刻触发第一次HTTP请求 - 后续组件侧
forkJoin订阅返回的response流时,shareReplay如果还没拿到第一次请求的结果,会再发起第二次请求,就出现了重复调用的情况
解决方案
使用RxJS的tap操作符处理缓存写入的副作用,完全去掉内部订阅即可,修改后的fetchShopOrders代码如下:
@Injectable({ providedIn: 'root' }) export class ApiManagerService { ... private readonly url = "..."; public ordersResponseCache = new Map<string, OrdersList>(); fetchShopOrders(status: string, quantity: number = 100) { const endpoint = this.url + "order/" + this.webzineId + "/order/?per_page=" + quantity + "&" + status; const ordersFromCache: OrdersList = this.ordersResponseCache.get(endpoint); if (ordersFromCache) { return of(ordersFromCache); } return this.http.get<OrdersList>(endpoint).pipe( tap(orders => this.ordersResponseCache.set(endpoint, orders)), shareReplay(1) ); } ... }
方案说明
tap是RxJS专门用于处理副作用的操作符,只会在流被订阅、且拿到上游返回的响应数据时才执行缓存写入逻辑,不会提前触发请求- 保留
shareReplay(1)可以保证同一时间多个订阅者订阅同一个未命中缓存的请求时,只会发起一次HTTP调用,所有订阅者共享同一份响应结果 - 缓存命中时直接返回
of()构造的冷Observable,不会发起任何网络请求,符合缓存设计预期
内容的提问来源于stack exchange,提问作者Manuel Brás
相关产品推荐
相关产品推荐

