从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.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
  



【问题讨论】:

在上一个控制台中未定义它的原因是因为您设置它的代码是异步的。此外 - 从不嵌套订阅 - 非常糟糕的做法。您可能想了解一下 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下载文件

SystemJS Typescript 输入冲突

如何在 Angular 5 中显示来自 Json Mapper 的数据?

如何从类属性 TypeScript 中侦听值更改 - Angular