angular - 尽管应用程序按预期运行,但无法读取未定义错误的属性

标签 angular typescript rxjs observable

我有一个应用程序从 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/

相关文章:

javascript - Angular 2 (click) 和 (dblclick) 在同一个元素上效果不佳?

javascript - 一个函数即可订阅并返回值 - 提高函数纯度?

angular - 如何从单个 Observable<[]> 返回两个修改后的 Observable<[]>

javascript - RxJS combineLatest 与 Angular 中的 startsWith 给出错误

angular - mat-table 动态创建列与静态更改表外观

typescript - RxJs 从 observable 获取值(value)

javascript - Angular 2 缓慢的初始加载

angular - 如何将类注入(inject)服务[Angular 6]

typescript - 无法从 Vue.js 中的方法访问数据(使用 Ionic)

angular - 等待两个 Observable 完成