Angular与RxJS:合并两个HTTP请求且立即发射外层结果
解决方案:分步发射原始订单+逐步更新客户信息的RxJS实现
针对你的需求,我们可以通过startWith、merge/concat和scan的组合,实现先发射原始订单列表、再逐步更新对应客户信息的效果,同时完全适配NgRx ComponentStore的effect要求。
核心思路
- 先获取原始订单列表并立即发射,让UI先渲染基础数据
- 对每个订单并行(或串行)发起客户信息请求
- 每次完成一个客户请求,就更新订单列表中对应的项,并发射更新后的完整列表
- 通过订单ID关联客户信息,确保对应关系准确
代码实现(适配ComponentStore)
假设你已有以下类型定义和API方法:
// 类型定义 interface Order { id: number; customerId: number; customer?: Customer; // 其他订单字段 } interface Customer { id: number; name: string; // 其他客户字段 } // 模拟API请求 const fetchOrders = () => this.http.get<Order[]>('/api/orders'); const fetchCustomer = (customerId: number) => this.http.get<Customer>(`/api/customers/${customerId}`);
在ComponentStore中实现对应的effect:
import { ComponentStore, effect, tap, ofType, switchMap, startWith, scan, merge, map, catchError, of } from '@ngrx/component-store'; @Injectable() export class OrderStore extends ComponentStore<{ orders: Order[] }> { // 定义action(示例) readonly loadOrders = createAction('[Order] Load Orders'); readonly actions$ = createEffect(() => this.actions$.pipe(ofType(this.loadOrders))); readonly loadOrdersWithCustomers = this.effect(() => { return this.actions$.pipe( ofType(this.loadOrders), switchMap(() => fetchOrders().pipe( switchMap(originalOrders => { // 为每个订单创建获取客户信息的Observable const customerUpdateStreams = originalOrders.map(order => fetchCustomer(order.customerId).pipe( map(customer => ({ ...order, customer })), // 处理单个客户请求失败的情况 catchError(() => of({ ...order, customer: null, loadFailed: true })) ) ); // 合并所有客户请求流,用scan累积更新订单列表 return merge(...customerUpdateStreams).pipe( // 初始值为原始订单列表,每次更新后返回新列表 scan((updatedOrders, updatedSingleOrder) => updatedOrders.map(o => o.id === updatedSingleOrder.id ? updatedSingleOrder : o ), originalOrders), // 先发射原始订单列表,再发射每次更新后的列表 startWith(originalOrders) ); }) ) ), // 将每次发射的订单列表更新到ComponentStore状态 tap(orders => this.patchState({ orders })) ); }); }
关键细节说明
- 订单与客户的关联:通过订单
id匹配更新后的单个订单,确保客户信息不会对应错误的订单 - 分步发射数据:
startWith(originalOrders)确保原始订单列表先被发射,UI可以立即渲染;后续每完成一个客户请求,scan就会生成并发射更新后的完整订单列表,UI逐步更新 - 请求控制:使用
merge实现并行请求客户信息(效率更高),如果需要串行请求(比如API有频率限制),替换为concat即可 - 错误处理:为单个客户请求添加
catchError,避免一个请求失败导致整个流中断,同时可以标记该订单的加载状态
内容的提问来源于stack exchange,提问作者cjs1978
相关产品推荐
相关产品推荐

