Firestore查询未删除联系人异常:返回Subscriber而非对象求助
问题描述
尝试从Firebase Firestore获取isDeleted为false的联系人信息,但代码未按预期工作:
- 代码返回Subscriber对象,无法直接访问
contact.contactName这类属性 where过滤语句未生效
相关代码(object-details.page.ts):
... contact: any = {}; ... if (this.contactId && this.contactId != undefined && this.contactId != "") { this.angularFirestore .collection("accounts") .doc(this.userId) .collection("contacts", (ref) => ref.where("isDeleted", "==", false)) .doc(this.contactId) .valueChanges() .subscribe((contact: any) => (this.contact = contact)); console.log("this.contact", this.contact); } else { console.log("No contact data available"); }
解决方案
1. 解决异步订阅导致的对象无法直接访问问题
valueChanges()返回的是Observable,订阅操作是异步的,你当前的console.log写在订阅外面,会先于回调执行,所以打印的是初始空对象,而非Firestore返回的真实数据。
修改方法:把数据处理逻辑(包括打印、属性访问)放到subscribe的回调函数内部:
if (this.contactId && this.contactId.trim() !== "") { this.angularFirestore .collection("accounts") .doc(this.userId) .collection("contacts") .doc(this.contactId) .valueChanges() .subscribe((contact: any) => { // 此处才能拿到真实的联系人数据 this.contact = contact; console.log("this.contact", this.contact); // 可直接访问 contact.contactName console.log("联系人名称", this.contact.contactName); }); } else { console.log("No contact data available"); }
2. 解决where过滤无效的问题
当前写法逻辑错误:先通过where过滤集合,再直接指定doc(this.contactId)获取单个文档,这会忽略之前的过滤条件——因为指定文档ID后,Firestore会直接返回该ID对应的文档,不管它是否符合isDeleted: false的条件。
正确处理方式有两种:
方式一:通过集合查询同时匹配ID和过滤条件
直接查询集合中同时满足文档ID和isDeleted条件的文档:
if (this.contactId && this.contactId.trim() !== "") { this.angularFirestore .collection("accounts") .doc(this.userId) .collection("contacts", ref => ref.where("__name__", "==", this.contactId) // 匹配文档ID的特殊字段 .where("isDeleted", "==", false) // 匹配未删除条件 ) .valueChanges() .subscribe((contacts: any[]) => { // 查询结果为数组,符合条件的文档最多一个 if (contacts.length > 0) { this.contact = contacts[0]; console.log("有效联系人", this.contact); } else { this.contact = {}; console.log("联系人已删除或不存在"); } }); } else { console.log("No contact data available"); }
方式二:先获取文档,再判断删除状态
如果不需要实时监听数据变化,可先获取文档快照,再在回调中判断isDeleted状态:
if (this.contactId && this.contactId.trim() !== "") { this.angularFirestore .collection("accounts") .doc(this.userId) .collection("contacts") .doc(this.contactId) .get() // 获取单次数据快照,而非实时监听 .subscribe((docSnapshot) => { if (docSnapshot.exists) { const contact = docSnapshot.data(); if (!contact.isDeleted) { this.contact = contact; console.log("有效联系人", this.contact); } else { this.contact = {}; console.log("联系人已删除"); } } else { console.log("联系人不存在"); } }); } else { console.log("No contact data available"); }
额外优化建议
- 简化条件判断:用
if (this.contactId?.trim())替代冗长的非空检查 - 避免使用
any类型,建议定义Contact接口规范数据结构:
interface Contact { contactName: string; isDeleted: boolean; // 补充其他联系人属性 } contact: Contact = {} as Contact;
内容的提问来源于stack exchange,提问作者vlntn
相关产品推荐
相关产品推荐

