如何在执行任务之前等待多个firebase查询完成



我正在想办法删除所有保存的用户数据,一旦删除了这些数据,请注销用户并在调用deleteUserAccount()时删除他们的帐户。

现在当用户按下";删除帐户";按钮,他们的帐户将被删除,但数据仍保留在firebase上,因为在deleteAllUserTicketData()函数有足够的时间执行查询并删除相应的文档之前调用了完成处理程序。

在执行完成处理程序之前,我如何等待查询执行和所有文档删除,以便注销用户并删除他们的帐户?

func deleteAllUserTicketData(completion: @escaping () -> Void) {
let group = DispatchGroup()
group.enter()
self.rootWsrCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for wsr in snapshot.documents{
print("Deleting WSR: (wsr)")
wsr.reference.delete()
}
group.leave()
}
group.enter()
self.rootExerciseCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for exercise in snapshot.documents {
print("Deleting Exercise: (exercise)")
exercise.reference.delete()
}
group.leave()
}
group.enter()
self.rootWorkoutsCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for workout in snapshot.documents {
print("Deleting Workout: (workout)")
workout.reference.delete()
}
group.leave()
}
group.notify(queue: DispatchQueue.global()) { [weak self] in
self?.workoutsCollection.daysCollection.removeAll()
print("Calling Notify Method")
completion()
}
}
//This method will only delete the user from the Firestore, but will not delete the User Auth credentials.
func deleteUserFromFirestore(completion: @escaping () -> Void) {
self.rootUserCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments { (querySnapshot, err) in
guard let snapshot = querySnapshot else { return }
for user in snapshot.documents {
print("Deleting User: (user)")
user.reference.delete()
}
completion()
}
}
func deleteUserAccount() {
deleteAllUserTicketData {
print("First Completion is called")
self.deleteUserFromFirestore {
print("Second Completion is called")
Auth.auth().currentUser?.delete()
}
}
}

}

您可以尝试DispatchGroup等待所有异步,然后在它们全部完成时触发。如果你enter()5次,你也需要leave()5次。您需要平衡leave()enter()。如果您对leave()的调用多于对enter()的调用,它将因调用不平衡而崩溃。

而且,如果您不需要制作实时观察器,请不要使用addSnapShotListener。请改用此https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document

这是您更新的逻辑〔第一次更新〕

func deleteAllUserTicketData(completion: @escaping () -> Void) {

let dispatchGroup = DispatchGroup()

// Inner function
func deleteWithWaiting(snapShot: QuerySnapshot?) {
guard let snapshot = querySnapshot else {
dispatchGroup.leave() // leave 1 after fetching documents
return
}

for document in snapshot.documents {
dispatchGroup.enter() // enter 2 before async delete
document.delete() { err in
if let err = err {
print("Error removing document: (err)")
} else {
print("Document successfully removed!")
}
dispatchGroup.leave() // leave 2 after async delete
}
}
dispatchGroup.leave() // leave 1 after fetching documents
}

// PLEASE use the .getDocuments() { (querySnapshot, err) in
// instead of .addSnapshotListener {(querySnapshot, err) in
// You just need to fetch data once, not making a new event listener, though it only triggers once.

dispatchGroup.enter() // enter 1 before fetching documents
self.rootWsrCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments() { (querySnapshot, err) in
deleteWithWaiting(snapShot: querySnapshot)
}

dispatchGroup.enter() // enter 1 before fetching documents
self.rootExerciseCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments() { (querySnapshot, err) in
deleteWithWaiting(snapShot: querySnapshot)
}

dispatchGroup.enter() // enter 1 before fetching documents
self.rootWorkoutsCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments() { (querySnapshot, err) in
deleteWithWaiting(snapShot: querySnapshot)
}

// 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) {
let dispatchGroup = DispatchGroup()

dispatchGroup.enter() // enter 1 before fetching documents
self.rootUserCollection?.whereField("uid", isEqualTo: userIdRef).getDocuments() { (querySnapshot, err) in
guard let snapshot = querySnapshot else {
dispatchGroup.leave() // leave 1 after fetching documents
return
}

for document in snapshot.documents {
dispatchGroup.enter() // enter 2 before async delete
document.delete() { err in
if let err = err {
print("Error removing document: (err)")
} else {
print("Document successfully removed!")
}
dispatchGroup.leave() // leave 2 after async delete
}
}
dispatchGroup.leave() // leave 1 after fetching documents
}

dispatchGroup.notify(queue: DispatchQueue.global()) {
completion() // now we finished the deleting
}
}
func deleteUserAccount() {
// Swich to Background Thread to perform big-calculation or long-waiting task
DispatchQueue.global().async { [weak self] in
self?.deleteAllUserTicketData {
self?.deleteUserFromFirestore {
Auth.auth().currentUser?.delete()

DispatchQueue.main.async { [weak self] in
// Update your new UI state here
self?.doSomething()
}
}
}
}
}

最新更新