Angular通过API请求服务状态后读取timestamp属性提示undefined问题
问题根因
有三个核心问题导致报错:
- 构造函数初始化
dataResults的逻辑错误
你使用for...in遍历数组dataArray,此时拿到的val是数组的下标字符串('0'/'1'/'2'),不是预期的服务名('import'/'cron'/'delta'),导致dataResults从初始化阶段就没有对应服务名的key,模板取值时自然找不到对应属性。 - 异步请求时序问题
API请求是异步操作,组件渲染完成时请求还未返回结果,此时就算初始化逻辑正确,dataResults对应key下的属性也是空值,直接读取timestamp也会触发报错。 - 代码笔误:错误处理逻辑中
else if (error.status = 200)是赋值操作,不是相等判断,逻辑完全不符合预期。
修复方案
第一步:修正构造函数的初始化逻辑
把for...in替换为for...of遍历拿到服务名,初始化对应key的空对象:
constructor( private _httpClient: HttpClient, @Inject(L10N_LOCALE) locale: L10nLocale, private translation: L10nTranslationService, private dialog: MatDialog ) { // 替换for...in为for...of遍历服务名 for (const val of this.dataArray) { this.dataResults[val] = {} as StatusElementInterface; } }
第二步:模板添加空值判断,避免异步未返回时报错
两种方案选一种即可:
- 方案1:使用Angular可选链运算符
{{ dataResults['import']?.timestamp }}
- 方案2:使用
*ngIf条件包裹
<ng-container *ngIf="dataResults['import'] && dataResults['import'].timestamp"> {{ dataResults['import'].timestamp }} </ng-container>
第三步:修正错误处理的笔误
// 把赋值=替换为全等判断=== else if (error.status === 200) { this.dialog.open(DialogOverviewExampleDialog, dialogConfig); }
可选优化:统一处理异步请求
如果需要所有请求返回后再渲染内容,可以用forkJoin合并所有请求,避免逐个订阅的时序问题:
import { forkJoin, of } from 'rxjs'; // ngAfterViewInit中替换原有循环请求的逻辑 const requests = this.dataArray.map(val => { const requestUrl = `${href}?type=${val}`; return this._httpClient.get<StatusInterface>(requestUrl).pipe( map(res => ({ key: val, data: res })), catchError(err => { // 错误处理逻辑 const dialogConfig = new MatDialogConfig(); if (err.status === 404 || err.status === 200) { dialogConfig.disableClose = true; dialogConfig.autoFocus = true; this.dialog.open(DialogOverviewExampleDialog, dialogConfig); } this.routeNotRegistered = true; return of({ key: val, data: {} as StatusElementInterface }); }) ); }); forkJoin(requests).subscribe(results => { results.forEach(({key, data}) => { this.dataResults[key] = data; }); });
内容的提问来源于stack exchange,提问作者Henning Möllendorf
相关产品推荐
相关产品推荐

