Angular TypeScript中访问Firestore返回字段与userid出现undefined问题
问题原因及修复方案
1. 订阅外打印userid为undefined的原因
subscribe是RxJS的异步回调逻辑,不会阻塞主线程代码执行。ngOnInit运行时会先执行订阅外的console.log(this.userid),此时Firebase Auth的用户状态回调还没有触发,this.userid还没有被赋值,自然返回undefined,所有需要用到userid的逻辑都必须放在订阅回调内部,或者通过RxJS操作符串联异步流程。
2. 无法访问this.eventList.eventID的原因
你调用collection('Events').valueChanges()返回的是集合查询结果数组,哪怕只有一条符合条件的数据,返回的也是包含单条对象的数组,而不是单个Event对象。直接访问数组的eventID属性当然会返回undefined,需要先取下标或者遍历数组才能拿到单条数据的属性:
// 比如拿第一条数据的eventID console.log(this.eventList[0]?.eventID) // 遍历拿所有eventID this.eventList.forEach(event => console.log(event.eventID))
额外注意:如果你要拿的eventID是Firestore自动生成的文档ID,valueChanges默认不会返回这个ID,只会返回文档内部存储的字段,需要换成snapshotChanges才能获取文档ID,示例写法如下。
优化后的代码示例
import { Component, OnInit, OnDestroy } from '@angular/core'; import { AngularFirestore } from '@angular/fire/compat/firestore'; import { AuthService } from '../auth.service'; import { Router } from '@angular/router'; import { switchMap, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; // 定义Event类型方便类型提示 interface Event { eventID?: string; title?: string; eventCreator: string; // 其他字段自行补充 } export class Tab1Page implements OnInit, OnDestroy { // 明确类型为Event数组 public eventList: Event[] = []; public userid: string; // 用于销毁时取消订阅,避免内存泄漏 private destroy$ = new Subject<void>(); constructor(private firestore: AngularFirestore, public fAuth: AuthService, public router: Router) {} ngOnInit(){ this.fAuth.firebaseAuth.user.pipe( // 用switchMap串联两个异步请求,避免嵌套订阅 takeUntil(this.destroy$), switchMap(user => { this.userid = user.uid; console.log(this.userid) // 这里可以正常拿到userid // 如果需要获取文档ID,把valueChanges换成snapshotChanges return this.firestore.collection<Event>('Events', ref => ref.where("eventCreator","==",this.userid)).snapshotChanges() }) ).subscribe(snapshots => { // 处理snapshot,同时拿到文档ID和字段数据 this.eventList = snapshots.map(snap => { const data = snap.payload.doc.data() as Event; // 把文档ID赋值给eventID,如果你需要的是文档自带ID的话 data.eventID = snap.payload.doc.id; return data; }) // 现在可以正常访问属性了 console.log(this.eventList) console.log(this.eventList[0]?.eventID) console.log(this.eventList[0]?.title) }); } ngOnDestroy() { // 组件销毁时取消所有订阅 this.destroy$.next(); this.destroy$.complete(); } }
内容的提问来源于stack exchange,提问作者motionless570
相关产品推荐
相关产品推荐

