[英]How to wait for multiple firebase queries to finish before executing a task?
I'm trying to figure out how to delete all saved User's data, and once that data is deleted, Signout the user and delete their account when deleteUserAccount() is called.我试图弄清楚如何删除所有已保存的用户数据,一旦删除该数据,在调用 deleteUserAccount() 时注销用户并删除他们的帐户。
Right now, when the User presses the "Delete Account" button, their account gets deleted, but the data still remains on firebase because the completion handler gets called before the deleteAllUserTicketData() function has enough time to execute the query and delete the appropriate documents.现在,当用户按下“删除帐户”按钮时,他们的帐户被删除,但数据仍保留在 firebase 上,因为完成处理程序在 deleteAllUserTicketData() 之前被调用 function 有足够的时间来执行查询并删除相应的文档.
My question is, how can I wait for the queries to execute and all the documents to get deleted before executing the completion handler in order to sign the user out and delete their account?我的问题是,如何在执行完成处理程序之前等待查询执行和所有文档被删除,以便注销用户并删除他们的帐户?
Much appreciated!非常感激! Thanks in advanced!
先谢谢了!
func deleteAllUserTicketData(completion: @escaping () -> Void) {
self.rootWsrCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for wsr in snapshot.documents{
print("Deleting WSR's")
self.rootWsrCollection!.document(wsr.documentID).delete()
}
}
self.rootExerciseCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for exercise in snapshot.documents {
print("Deleting Exercises")
self.rootExerciseCollection!.document(exercise.documentID).delete()
}
}
self.rootWorkoutsCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for workout in snapshot.documents {
print("Deleting Workouts")
self.rootWorkoutsCollection!.document(workout.documentID).delete()
}
}
self.workoutsCollection.daysCollection.removeAll()
completion()
}
func deleteUserFromFirestore(completion: @escaping () -> Void) {
self.rootUserCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for user in snapshot.documents {
self.rootUserCollection!.document(user.documentID).delete()
}
completion()
}
}
func deleteUserAccount() {
deleteAllUserTicketData {
self.deleteUserFromFirestore {
Auth.auth().currentUser?.delete()
}
}
}
You can try DispatchGroup
to wait for all async then trigger when they all finish.您可以尝试
DispatchGroup
等待所有异步,然后在它们全部完成时触发。 If you enter()
5 times, you also need to leave()
5 times.如果
enter()
5 次,还需要leave()
5 次。 You need to balance the leave()
with enter()
.您需要平衡
leave()
和enter()
。 If you call leave()
more than enter()
, it will crash because unbalanced call.如果你调用
leave()
多于enter()
,它会因为不平衡调用而崩溃。
And, please do not use addSnapShotListener if you don't need to make a realtime observer.而且,如果您不需要实时观察者,请不要使用 addSnapShotListener。 Use this instead https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document
改用这个https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document
Here is you updated logic:这是您更新的逻辑:
func deleteAllUserTicketData(completion: @escaping () -> Void) {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
self.rootWsrCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener {[weak self] (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for wsr in snapshot.documents{
print("Deleting WSR's")
self?.rootWsrCollection!.document(wsr.documentID).delete()
// use can try this for shortened call
wsr.delete()
}
// Suppose that delete() is success
dispatchGroup.leave()
}
dispatchGroup.enter()
self.rootExerciseCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener {(querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for exercise in snapshot.documents {
print("Deleting Exercises")
exercise.delete()
}
dispatchGroup.leave()
}
dispatchGroup.enter()
self.rootWorkoutsCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for workout in snapshot.documents {
print("Deleting Workouts")
workout.delete()
}
dispatchGroup.leave()
}
// When no waiting item remains (all entered and left), this block will be triggered on queue, in this case, is it Global queue (like background thread
// So if you need to update UI from this, you need to switch to Main Queue or DispatchQueue.main.async { }
dispatchGroup.notify(queue: DispatchQueue.global()) { [weak self] in
// refer to self with a weak reference to avoid retain cycle, prevent memory leak
self?.workoutsCollection.daysCollection.removeAll()
completion()
}
}
func deleteUserFromFirestore(completion: @escaping () -> Void) {
self.rootUserCollection?.whereField("uid", isEqualTo: userIdRef).addSnapshotListener { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for user in snapshot.documents {
user.delete()
}
completion()
}
}
func deleteUserAccount() {
self.deleteAllUserTicketData { [weak self] in
self?.deleteUserFromFirestore {
Auth.auth().currentUser?.delete()
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.