如何在Angular服务中实现同步方法?解决并发重复请求问题
解决Angular服务方法重复请求后端的问题
Angular没有提供类似Java/C#中synchronized的原生关键字,但可以借助RxJS的特性实现类似的“请求同步”效果,避免多个组件同时调用服务方法时重复发起后端请求。
核心思路是缓存当前正在进行的HTTP请求Observable,让后续请求直接订阅这个已存在的请求,而不是重新发起新请求。具体实现步骤如下:
修改服务代码
在CryptoMarketService中添加一个私有变量存储正在进行的请求,然后修改getActiveOrders方法:
export class CryptoMarketService implements MarketService { private _activeOrdersCache: Cache<Array<Order>> = new Cache<Array<Order>>(); // 新增:存储当前正在进行的请求Observable private _activeOrdersRequest$: Observable<Array<Order>> | null = null; getActiveOrders(): Observable<Array<Order>> { // 1. 优先返回缓存数据 if (this._activeOrdersCache.hasCache()) { return of(this._activeOrdersCache.get()); } // 2. 如果已有正在进行的请求,直接返回该请求的Observable if (this._activeOrdersRequest$) { return this._activeOrdersRequest$; } // 3. 发起新请求并缓存请求Observable this._activeOrdersRequest$ = this.httpClient.get('/market/orders/active') .pipe( map((res: any) => Order.fromJsonArray(res)), tap((activeOrders: Array<Order>) => { this._activeOrdersCache.set(activeOrders, 5, TimeUnit.MINUTES); }), // 请求完成(成功/失败)后清空请求标记,避免后续请求被阻塞 finalize(() => { this._activeOrdersRequest$ = null; }) ); return this._activeOrdersRequest$; } }
方案原理
- 第一个请求触发时,缓存为空且无正在进行的请求,因此发起HTTP请求并将该Observable存入
_activeOrdersRequest$。 - 后续同时调用的请求会直接返回这个已存在的Observable,共享同一个HTTP请求的响应结果,彻底避免重复请求后端。
- 请求完成后(无论成功或失败),
finalize操作符会清空_activeOrdersRequest$,确保缓存过期后,下一次请求能正常发起新的后端调用。
额外说明
如果需要处理请求失败的重试逻辑,可以在pipe中添加retry操作符,但要注意配合finalize确保请求标记最终会被清空,避免出现永久阻塞的情况。
内容的提问来源于stack exchange,提问作者Alexander Kozlov
相关产品推荐
相关产品推荐

