我有一个应用程序从 api 获取一些数据并将其写入我的模板。我可以 console.log
数据并且数据按预期出现在模板中。但是控制台还是报错
cannot read property X of undefined.
我不明白为什么会这样,因为我需要的数据的 console.log
(它说是未定义的)出现在错误之前!
我试过使用 ngOnInit
而不是 ngAfterViewInit
并且我试过使用 async pipe
,但是这些都不适合我.我还尝试将 reloadanimals
主题从主题切换到 BehaviourSubject。但是,我可能一直以错误的方式实现它们,因为我对 Angular 还是比较陌生。
我的模板模型
<div class="cards">
<ng-container *ngIf="animaltypes$; else elser" class="mat-elevation-z4">
<ng-container *ngFor="let animalname of ['frog', 'bear', 'cat']">
<mat-card *ngIf="animaltypes$[animalname]; let animal" class="mat-elevation-z4">
<mat-card-title class="animal-title">
Animal: {{ animal.name }}
</mat-card-title>
<mat-card-content class="animal-status">
Current Animal Info:
<span *ngIf="animal.build_version; else elseBlock">
Version {{ animal.facts }}({{ animal.foods }})
</span>
<ng-template #elseBlock><span>No Animal</span></ng-template>
</mat-card-content>
<mat-card-content class="animal-status">
Pending Info:
<span *ngIf="pendingData[animal.name].length > 0; else elseBlock">
Version
<span *ngFor="let pendingAnimal of pendingData[animal.name]">
{{ pendingAnimal.facts }}({{ pendingAnimal.foods }})
</span>
</span>
<ng-template #elseBlock><span>No Animal</span></ng-template>
</mat-card-content>
</mat-card>
</ng-container>
</ng-container>
<ng-template #elser><span>else</span></ng-template>
</div>
我的 typescript 模型
constructor(
private DataService: AnimalDataService,
private route: ActivatedRoute
) {}
public type: string
isLoadingResults: boolean = true
public pendingData
public animaltypes$ = {}
getAnimals(type: string): Observable<AnimalResponse> {
return this.DataService.getanimals() as Observable<AnimalResponse>
}
getPendingAnimals(type: string) {
this.DataService.getpendinganimals().subscribe(res => {
this.pendingData = res
})
}
ngAfterViewInit() {
merge(this.DataService.reloadAnimals, this.route.paramMap)
.pipe(
startWith({ stable: null, testing: null, edge: null }),
switchMap(() => {
this.route.paramMap.subscribe(paramMap => {
this.type = paramMap.get("name")
})
this.isLoadingResults = true
this.pendingData = this.getPendingAnimals(this.type)
return this.getPendingAnimals(this.type)
}),
map(data => {
this.getPendingAnimals(this.type)
let animals = new Observable<any>()
for (let animal in data) {
if (data[animal]) {
data[animal].name = animal
} else {
data[animal] = { name: animal }
}
animals[animal] = data[animal]
}
return animals
})
)
.subscribe(animals => {
this.animaltypes$ = animals
console.log(this.animaltypes$)
return this.animaltypes$
})
return this.pendingData
}
dataservice
只有一些接口(interface)和基本的 get 请求,我不认为这是问题所在。
我试图创建一个 plunkr,但我花了很长时间让它工作,我想我应该在这里发帖然后再回来。 如果有任何帮助,就在这里。由于某种原因,字符串插值似乎根本没有在我的 plunkr 中发生,但这是我第一次使用 plunker。
https://next.plnkr.co/plunk/IfgoJiXSaPzMIvgd
一切都在我的实际应用程序中正常显示,这只是控制台错误
cannot read property "frog" of undefined"
只有当我重新加载结果时才会发生这种情况。这让我觉得它可能与 reloadAnimals 主题有关。
最佳答案
我认为问题如下:
- 您的组件已创建
- 组件触发数据加载
- 在加载过程中,组件会尝试渲染
==> 但是数据现在没有加载,所以尝试访问animal
导致“无法读取未定义的属性“frog””。 - 几毫秒后,数据被检索
=> 再次渲染组件,这次带有内容
console.log 首先是令人恼火的。但我假设你使用的是 chrome。在那里你需要知道一个关于 console.log 的特殊行为。它不是在执行 console.log
的时间点评估其内容,而是在您查看它(展开它)时评估它的内容。
这意味着当您查看结果时,它会向您显示更新的内容。
如何解决这个问题
一种简单的解决方案是使用“?” html 中的运算符。
{{ animal?.name }}
另一种解决方案是在数据完全加载之前不显示主要内容。
解决方案取决于您想要提供什么样的用户体验。
亲切的问候
简
关于angular - 尽管应用程序按预期运行,但无法读取未定义错误的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57508796/