从Angular TypeScript中来自firestore的数据中获取未定义
Posted
技术标签:
【中文标题】从Angular TypeScript中来自firestore的数据中获取未定义【英文标题】:getting undefined from data coming from firestore in Angular TypeScript 【发布时间】:2021-12-31 13:23:10 【问题描述】:我想从名为 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
【问题讨论】:
在上一个控制台中未定义它的原因是因为您设置它的代码是异步的。此外 - 从不嵌套订阅 - 非常糟糕的做法。您可能想了解一下 observables / RxJs 的工作原理。 【参考方案1】:作为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
等来访问每个元素。
【讨论】:
那么我怎样才能在订阅函数之外定义 userid 和 eventID 呢?【参考方案2】:要解决嵌套订阅时出现的undefined
数据响应问题,请使用RxJS switchMap()
运算符将外部可观察对象的结果从fAuth.firebaseAuth.user
可观察对象传递到内部可观察对象,即@987654326 @ observable,从那里你可以在一个订阅中从内部 observable 的流式响应中分配事件列表:
像这样(我不确定您的事件数据的结构 - 它是一个数组还是一个类/接口,它是一个包含数组的标头,所以我放置了一个 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 同时处理并在它们都有结果时处理它们
从他们各自的 observables 中准备好。
从 HTML 模板访问另一个事件处理程序中的变量。
要试验和测试上述嵌套的可观察对象,请先使用简单的模拟服务,然后将您的可观察对象附加到实时服务。
我推荐一个很好的参考网站here(我也经常使用),以进一步了解(和示例)以及更多关于如何在这些情况下使用 RxJS 以及 SO 中的其他帖子。
【讨论】:
我可以在 .subscribe() 函数之外使用变量吗? 您仍然可以在 subscribe() 之外使用变量。我将扩展我的答案以澄清与变量相关的可能和不相关的内容。 这很好用。谢谢!以上是关于从Angular TypeScript中来自firestore的数据中获取未定义的主要内容,如果未能解决你的问题,请参考以下文章
如何为来自 SpringBoot 后端代码的嵌套 JSON 响应在 angular8(TypeScript) 或更高版本中定义模型类
如何显示来自 angular 8 typescript 订阅的错误消息?
typescript 来自Laravel API的Angular下载文件