Angular新手咨询subscribe订阅内更新mat table数据源datasource的方案
问题根本原因
- 异步时序错误:
adminService.vehicles是异步请求,你在fleets接口返回后直接赋值数据源,此时所有嵌套的车辆请求还未完成,统计数据还未填充到车队对象中。 - 数据结构不兼容:你把
fleetTableData初始化为数组[],但用fleetId作为键名赋值,本质是把数组当作普通对象使用,而MatTableDataSource要求传入的是索引为连续数字的标准数组,直接传入你构造的结构会导致表格无法识别数据。 - 嵌套订阅不符合RxJS最佳实践,容易出现内存泄漏、时序混乱问题。
修复方案
首先导入需要的RxJS操作符:
import { forkJoin, switchMap, map } from 'rxjs';
修复后的refresh方法代码:
refresh(): void { const data = {}; this.adminService.fleets(data).pipe( // 承接车队列表返回结果,批量发起所有车队的车辆请求 switchMap(fleets => { // 先给每个车队初始化统计字段 const processedFleets = fleets.map(fleet => { if (!fleet.fleetTotals) { fleet.fleetTotals = { totalVehicles: 0, totalActiveVehicles: 0, totalStatusTestedVehicles: 0 }; } return fleet; }); // 构造所有车辆请求的Observable数组 const vehicleRequests = processedFleets.map(fleet => this.adminService.vehicles({fleetId: fleet.fleetId}).pipe( // 车辆请求返回后统计数据,挂载到对应车队对象上 map(vehicles => { vehicles.forEach(vehicle => { fleet.fleetTotals.totalVehicles++; if (vehicle.commissioning) { if (vehicle.commissioning.commissionStatus === 'tested') { fleet.fleetTotals.totalStatusTestedVehicles++; } if (vehicle.commissioning.commissionStatus === 'active') { fleet.fleetTotals.totalActiveVehicles++; } } }); return fleet; }) ) ); // 等待所有车辆请求全部完成 return forkJoin(vehicleRequests); }) ).subscribe(processedFleetList => { // 所有数据处理完成后再更新数据源 this.dataSource = new MatTableDataSource(processedFleetList); this.dataSource.sort = this.sort; console.log(processedFleetList); }); }
关键改动说明
- 用
switchMap承接车队接口的返回结果,避免嵌套订阅 - 用
forkJoin批量等待所有车队的车辆请求全部完成后再更新数据源,保证统计数据完整 - 直接构造标准数组传给
MatTableDataSource,符合组件的数据格式要求 - 移除了没必要的
that = this写法,箭头函数会自动绑定this上下文
内容的提问来源于stack exchange,提问作者Alexander_Barton
相关产品推荐
相关产品推荐

