You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular项目中TypeScript读取Firestore数据失败问题求助

一、库选择建议:优先用模块化API

当前AngularFire推荐使用模块化API(从@angular/fire/firestore导入的方法),compat包(如AngularFirestore)仅用于旧项目迁移,新项目直接用模块化API即可——它支持树摇优化,打包体积更小,且和Firebase Web SDK v9+的原生API完全对齐。

你可以直接移除服务中的AngularFirestore依赖,只保留Firestore注入。


二、获取数据失败的核心问题

你的代码里有两个关键错误:

  1. 文档ID匹配错误:在rejectFriendRequest中用了JSON.stringify(currentUser),如果currentUser本身是字符串(比如邮箱),这会把ID变成带引号的格式(例如"user@example.com"),但控制台里的文档ID是不带引号的原始邮箱,导致后续获取时ID不匹配。
  2. 不必要的异步操作:doc(colRef, id)是同步方法,不需要加await。

三、修正后的代码示例

1. 精简FirestoreService

import { Injectable } from '@angular/core';
import {
  Firestore,
  doc,
  getDoc,
  docData,
  updateDoc,
  arrayRemove,
  arrayUnion
} from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { ProfileUser } from '../model/profile-user';

@Injectable({ providedIn: 'root' })
export class FirestoreService {
  constructor(private firestore: Firestore) {}

  // 修正更新方法:移除JSON.stringify
  async rejectFriendRequest(rejectedUser: string, currentUser: string) {
    const recipientRef = doc(this.firestore, 'users', currentUser);
    await updateDoc(recipientRef, {
      invitationsFrom: arrayRemove(rejectedUser),
      rejectedInvitation: arrayUnion(rejectedUser)
    });
  }

  // 方式1:用Promise获取数据(适合单次查询)
  async getUser(id: string): Promise<ProfileUser | null> {
    const docRef = doc(this.firestore, 'users', id);
    const docSnap = await getDoc(docRef);
    
    if (docSnap.exists()) {
      return docSnap.data() as ProfileUser;
    } else {
      console.log('目标文档不存在');
      return null;
    }
  }

  // 方式2:用Observable获取数据(Angular响应式场景推荐)
  getUser$ (id: string): Observable<ProfileUser | null> {
    const docRef = doc(this.firestore, 'users', id);
    return docData(docRef) as Observable<ProfileUser | null>;
  }
}

2. 组件中调用示例

import { Component, OnInit } from '@angular/core';
import { FirestoreService } from './services/firestore.service';

@Component({ selector: 'app-user', templateUrl: './user.component.html' })
export class UserComponent implements OnInit {
  constructor(private firestoreService: FirestoreService) {}

  ngOnInit() {
    const userId = 'user@example.com'; // 确保和Firestore控制台的文档ID完全一致
    
    // 用Observable监听数据变化
    this.firestoreService.getUser$(userId).subscribe(user => {
      if (user) {
        console.log('用户数据:', user);
      }
    });

    // 或用Promise单次获取
    this.firestoreService.getUser(userId).then(user => {
      console.log('单次获取用户:', user);
    });
  }
}

四、邮箱作为文档ID的注意事项

Firestore文档ID支持包含.,之前找不到文档不是因为.,而是错误地用JSON.stringify给邮箱加了引号。只要确保创建文档、更新文档、获取文档时用的是原始邮箱字符串,就不会有问题。


五、排查小技巧

  1. 打开Firestore控制台,确认目标文档的ID和你传入的id完全一致(包括大小写、无多余符号);
  2. 临时放宽Firestore规则(测试用):设置allow read, write: if true;,排除权限问题;
  3. 用getDoc的方式可以明确判断文档是否存在,比直接订阅docData更方便排查问题。

内容的提问来源于stack exchange,提问作者Maczosss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:00:59