无法用async调用函数时,如何等待Firestore查询完成再添加监听器?
解决Firestore数据获取与监听器顺序问题
你当前的代码问题在于getDocuments是异步操作,调用后会立刻执行后面的contentUpdates,导致监听器在数据获取完成前就被添加。因为无法使用async/await,我们可以通过调整回调内的代码执行顺序来实现需求:
修改后的代码
private var firestoreListener: ListenerRegistration? func createNewContent(firebasePath: Query) { // 先移除已存在的监听器,重置状态 self.firestoreListener?.remove() self.firestoreListener = nil let contentRef = firebasePath contentRef.getDocuments() { [weak self] (querySnapshot, err) in guard let self = self else { return } if let err = err { print("获取初始数据失败: \(err.localizedDescription)") return } guard let querySnapshot = querySnapshot else { print("未获取到快照数据") return } // 处理获取到的初始数据(修正原逻辑:当文档数不为0时遍历) if !querySnapshot.documents.isEmpty { for document in querySnapshot.documents { // 处理Firestore文档数据 let data = document.data() // ... 你的数据处理逻辑 } } // 初始数据处理完成后,添加监听器 self.contentUpdates(firebasePath: firebasePath) } } func contentUpdates(firebasePath: Query) { firestoreListener = firebasePath.addSnapshotListener() { [weak self] (querySnapshot, err) in guard let self = self else { return } guard let snapshot = querySnapshot else { print("获取快照更新失败: \(err!.localizedDescription)") return } snapshot.documentChanges.forEach { diff in if diff.type == .added { // 处理新增文档的更新逻辑 } // 可根据需求添加.modified/.removed的处理 } } }
关键调整说明
- 重置监听器:每次调用
createNewContent时先移除旧监听器并置空,避免重复监听或内存泄漏 - 保证执行顺序:将
contentUpdates的调用移到getDocuments的闭包内部,确保只有在初始数据获取并处理完成后才添加监听器 - 安全调用:使用
[weak self]避免循环引用,同时在闭包内解包self保证安全 - 逻辑修正:原代码中
querySnapshot!.documents.count == 0的判断逻辑有误,改为!querySnapshot.documents.isEmpty来遍历有效数据
内容的提问来源于stack exchange,提问作者Redstain
相关产品推荐
相关产品推荐

