本文介绍如何安全、健壮地从 API 响应中提取 loss、break 和 kpi 多个嵌套数组的指定字段值,并将其结构化映射至目标表单模型,同时处理字段缺失与类型转换问题。
本文介绍如何安全、健壮地从 api 响应中提取 `loss`、`break` 和 `kpi` 多个嵌套数组的指定字段值,并将其结构化映射至目标表单模型,同时处理字段缺失与类型转换问题。
在 Angular 8(及后续版本)的实际开发中,后端常返回结构不完全统一的嵌套 JSON 数据——例如 loss、break、kpi 等字段可能为空数组、缺失或包含多条记录。若直接使用 for...of 遍历 resp(误将整个响应对象当作数组),或未做存在性校验就访问 resp.loss[0].duration,极易触发 Cannot read property 'xxx' of undefined 运行时错误。
以下是一个类型安全、可维护、零依赖的解决方案,适用于 prepareFormForImport() 类型的表单初始化逻辑:
interface ApiResponse { factoryId: string; loss?: Array<{ lossType: string; duration: string }>; break?: Array<{ lossType: string; duration: string }>; kpi?: Array<{ mpl: string }>;}interface FormModel { factoryId: string | null; availableTime: { bankHoliday: number; breakDownTime: number; }; operatingTime: { maintenanceTime: number; }; uom: number;}prepareFormForImport(resp: ApiResponse): FormModel { // ✅ 安全读取:使用可选链(?.)和空值合并(??)避免报错 const bankHoliday = resp.loss?.find(item => item.lossType === 'Bank Holidays')?.duration ?? '0'; const breakDownTime = resp.loss?.find(item => item.lossType === 'Quality Time')?.duration ?? '0'; const maintenanceTime = resp['break']?.find(item => item.lossType === 'Format')?.duration ?? '0'; // 注意:break 是 JS 保留字,需用方括号访问 const mplValue = resp.kpi?.[0]?.mpl ?? '0'; return { factoryId: resp.factoryId || null, availableTime: { bankHoliday: parseFloat(bankHoliday) || 0, breakDownTime: parseFloat(breakDownTime) || 0, }, operatingTime: { maintenanceTime: parseFloat(maintenanceTime) || 0, }, uom: parseFloat(mplValue) || 0, };}
const apiResponse = { "factoryId": "A_0421", "loss": [ { "lossType": "Planned Stoppage Time", "duration": "1111" }, { "lossType": "Quality Time", "duration": "2222" } ], "break": [ { "lossType": "Format", "duration": "5.749999", "eventCount": "2" } ], "kpi": [ { "mpl": "16556.598475000053" } ]};const formModel = this.prepareFormForImport(apiResponse);console.log(formModel);// 输出:// {// factoryId: "A_0421",// availableTime: { bankHoliday: 0, breakDownTime: 2222 },// operatingTime: { maintenanceTime: 5.749999 },// uom: 16556.598475000053// }
该方案兼顾性能(单次遍历各数组)、可读性(语义化查找)与健壮性(全面兜底),是 Angular 表单初始化场景下的推荐实践。