简体   繁体   English

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

[英]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.

相关问题 在 Flutter 中呈现小部件之前,如何等待异步 function 完成执行 - How do I wait for an async function to finish executing before rendering a widget in Flutter 如何在继续之前等待 getDownloadURL 完成? - How to wait for getDownloadURL to finish before proceeding? 如何让我的程序在执行 function 之前等待 Firebase 的数据? - How can make my Program wait for Firebase's data before executing a function? 如何等到从 Firebase 下载完成后才执行完成 swift - How to wait till download from Firebase Storage is completed before executing a completion swift 在返回之前等待完成处理程序完成 - Wait for completion handler to finish before returning 如何等待firebase存储上传图片后再使用? - How to wait for firebase storage to upload image before using it? 在 React 中访问 firebase 文档之前等待 UserID - Wait for UserID before accessing firebase documents in react 如何让 airflow dag 等待 VM 在执行下一个任务之前完成其工作 - how to make airflow dag wait VM to finishes its job before doing the next task 如何调用 function 但不要等待完成 - ASP.NET - How to invoke a function but don't wait to finish - ASP.NET 在使用 reactjs 发送 POST 请求之前,我如何等待 firebase 检查用户是否有效? - how can i wait for firebase to check the user is valid before sending a POST request with reactjs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM