从 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.eventID
或 this.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
因为异步内部可观察对象的执行尚未完成已完成,但尚未执行其处理程序中的代码来初始化变量。
解决订阅块外的变量访问问题的方法包括使用:
- 组件 HTML 模板中的
async pipe
。 (转换
首先是一个 Observable 的变量。
- 使用另一种RxJS方法如
combinelatest()
订阅
同时观察并在它们都有结果时处理它们
从他们各自的 observables 准备好。
- 从 HTML 模板访问另一个事件处理程序中的变量。
要试验和测试上述嵌套的可观察对象,请先使用简单的模拟服务,然后将您的可观察对象附加到实时服务。
我推荐一个很好的参考站点 here(我也经常使用它)以进一步了解(和示例)以及更多关于如何在这些情况下使用 RxJS 的信息,当然还有 SO 中的其他帖子。
我想从名为 Events 的 firestore 集合中获取 eventID 的值。我可以在我的应用程序中获取并显示我的 firestore 集合中的所有事件,但我需要这个 eventID
来完成其他功能。
我是 TS 和 Angular 的新手,不明白为什么这不起作用
当我在 auth 函数中记录我的 userid
变量时,它工作正常并检索值,但如果我在函数外这样做,它会给出未定义的。
此外,当我记录我创建的用于存储来自 firestore 的信息的整个 eventList
变量时,它会记录所有信息,但是如果我尝试检索任何内容,例如 this.eventList.eventID
或 this.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
因为异步内部可观察对象的执行尚未完成已完成,但尚未执行其处理程序中的代码来初始化变量。
解决订阅块外的变量访问问题的方法包括使用:
- 组件 HTML 模板中的
async pipe
。 (转换 首先是一个 Observable 的变量。 - 使用另一种RxJS方法如
combinelatest()
订阅 同时观察并在它们都有结果时处理它们 从他们各自的 observables 准备好。 - 从 HTML 模板访问另一个事件处理程序中的变量。
要试验和测试上述嵌套的可观察对象,请先使用简单的模拟服务,然后将您的可观察对象附加到实时服务。
我推荐一个很好的参考站点 here(我也经常使用它)以进一步了解(和示例)以及更多关于如何在这些情况下使用 RxJS 的信息,当然还有 SO 中的其他帖子。