从 Angular TypeScript 中来自 firestore 的数据中获取未定义

getting undefined from data coming from firestore in Angular TypeScript

我想从名为 Events 的 firestore 集合中获取 eventID 的值。我可以在我的应用程序中获取并显示我的 firestore 集合中的所有事件,但我需要这个 eventID 来完成其他功能。

我是 TS 和 Angular 的新手,不明白为什么这不起作用

当我在 auth 函数中记录我的 userid 变量时,它工作正常并检索值,但如果我在函数外这样做,它会给出未定义的。

此外,当我记录我创建的用于存储来自 firestore 的信息的整个 eventList 变量时,它会记录所有信息,但是如果我尝试检索任何内容,例如 this.eventList.eventIDthis.eventList.title 它记录未定义。

我做错了什么?

这是我的代码:

import { Component,OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '@angular/fire/compat/firestore';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
import { async } from '@firebase/util';

export class Tab1Page implements OnInit {

  public eventList;
  public userid;
  constructor(private firestore: AngularFirestore, public fAuth: AuthService, public router: Router) {}

  ngOnInit(){

    this.fAuth.firebaseAuth.user.subscribe(res => {
      this.userid = res.uid; //current logged in user id

      //fetch only events logged in user created
      this.firestore.collection('Events',ref=>ref.where("eventCreator","==",this.userid)).valueChanges().subscribe(event => { 

        this.eventList = event

        console.log(this.eventList)//logs all the info from firestore
        console.log(this.eventList.eventID)//logs undefined
        console.log(this.userid)//logs the userid
      });
    });
    console.log(this.userid)//logs undefined
  }


}

作为console.log(this.userid) // logs undefined

因为 @MikeOne 引用 subscribe 中的函数是异步的。这些功能通常会在稍后执行。所以在console.log(this.userid)//logs undefined被执行的时候,this.userid = res.uid;还没有被执行。

作为console.log(this.eventList.eventID) // logs undefined

我猜this.eventList是数组。尝试 this.eventList[0].eventID 等访问每个元素。

为了解决嵌套订阅发生的 undefined 数据响应问题,使用 RxJS switchMap() 运算符将外部可观察对象的结果从 fAuth.firebaseAuth.user 可观察对象传递到inner observable,这是 this.firestore.collection.. observable,从那里你可以从内部 observable 的流式响应中分配事件列表,所有这些都在一个订阅中:

像这样(我不确定你的事件数据的结构——要么是一个数组,要么是一个 class/interface,它是一个包含数组的 header,所以我放置了一个 any 作为响应类型):

this.fAuth.firebaseAuth.user
.pipe(
    switchMap((res: any) => {
        this.userid = res.uid; //current logged in user id

        //fetch only events logged in user created
        const eventListObservable: Observable<any> =                 
            this.firestore.collection('Events',ref => 
                ref.where("eventCreator","==",res.uid))
                .valueChanges()
                .pipe(
                    map((event: any) =>
                    {             
                        this.eventList = event;
 
                        console.log(event); //logs all the info from firestore
                        console.log(event.eventid); //logs event id
                        console.log(user.id); //logs the userid

                        return event;
                    })             
                 );
        return eventListObservable;
    })
)
.subscribe();

作为最佳实践,您可以将以上内容分配给 subscription 并稍后在 ngDestroy() 处理程序中释放它。

遇到的一个常见问题是能够访问 subscribe() 块之外的变量,并在 this question 中提出。如果您尝试在 subscribe() 块之外(和之后)访问组件的 event 变量,则访问时该变量将为 undefined 因为异步内部可观察对象的执行尚未完成已完成,但尚未执行其处理程序中的代码来初始化变量。

解决订阅块外的变量访问问题的方法包括使用:

  1. 组件 HTML 模板中的 async pipe。 (转换 首先是一个 Observable 的变量。
  2. 使用另一种RxJS方法如combinelatest()订阅 同时观察并在它们都有结果时处理它们 从他们各自的 observables 准备好。
  3. 从 HTML 模板访问另一个事件处理程序中的变量。

要试验和测试上述嵌套的可观察对象,请先使用简单的模拟服务,然后将您的可观察对象附加到实时服务。

我推荐一个很好的参考站点 here(我也经常使用它)以进一步了解(和示例)以及更多关于如何在这些情况下使用 RxJS 的信息,当然还有 SO 中的其他帖子。