使用嵌套异步 Firebase 调用 SwiftUI

Working with nested async Firebase calls SwiftUI

我对异步函数比较陌生,我知道 firebase getDocument 和 getDocuments 调用是异步的。在我继续我在代码中所做的事情之前,我希望这两个调用都完成。我一直在尝试通过调度组来实现这一点,但到目前为止一直没有成功。我有如下代码:

                
                let myGroup = DispatchGroup()
                self.errorMessage = ""
                let usersRef = self.db.collection("Users").document("Users").collection("Users")
                if self.test == false {
                    self.errorMessage = "test failed"
                } else{
                    //first async call
                    myGroup.enter()
                    usersRef.getDocuments {(snap, err) in
                        //basically getting every username
                        for document in snap!.documents{
                            print("loop")
                            let user = document["username"] as! String
                            let userRef = usersRef.document(user)
                            //second async call
                            userRef.getDocument { (snapshot, err) in
                                if err != nil {
                                    print(err)
                                } else {
                                    let self.error = snapshot!["error"] as! Bool
                                    if self.error == true{
                                        self.errorMessage = "error"
                                        print("error")
                                    }
                                    print("what3")
                                }
                                print("what2")
                            }
                            print("what1")
                        }
                        myGroup.leave()
                        print("what4")
                    }
                    //RIGHT HERE I WANT TO CONTINUE WHAT I WAS DOING BEFORE
                    myGroup.notify(queue: DispatchQueue.global(qos: .background)) {
                        print("HERE I SHOULD BE DONE")
                    }
                    
                    print("what5")
                }

但是,这会产生如下内容:

what5
loop
what1
loop
what1
loop
what1
loop
what1
loop
what1
loop
what1
what4
HERE I SHOULD BE DONE
error
what3
what2
error
what3
what2
what3
what2
error
what3
what2
what3
what2
error
what3
what2

所以看起来第一个异步调用正在完成,但第二个继续执行。我想等第二个结束再继续。

如有任何关于如何修改此代码的建议,我们将不胜感激。 谢谢

嵌套的异步代码可能会让人头疼,如果不牢牢掌握 Grand-Central-Dispatch 就很难管理。我建议您使用像 AwaitKit 或 [=12= 这样的库] 专门为此目的而设计的。掌握这些库需要一些时间,但一旦完成,它们在这种情况下将非常有用,您将能够以同步方式处理异步代码。您可以查看这些库 here

第二次调用getDocuments时需要重新入群。因为它也将是异步的。这样的事情应该可以解决问题:

let myGroup = DispatchGroup()
        //Enter first time for first async call
         myGroup.enter()
         self.errorMessage = ""
         let usersRef = self.db.collection("Users").document("Users").collection("Users")
         if self.test == false {
             self.errorMessage = "test failed"
         } else{
            usersRef.getDocuments {(snap, err) in //Starting first async call
                
                for document in snap!.documents{
                    print("loop")
                    let user = document["username"] as! String
                    let userRef = usersRef.document(user)
                    
                    //Enter second time for second async call
                    myGroup.enter()
                    userRef.getDocument { (snapshot, err) in // starting second async call
                        if err != nil {
                            print(err)
                        } else {
                            let self.error = snapshot!["error"] as! Bool
                            if self.error == true{
                                self.errorMessage = "error"
                                print("error")
                            }
                            print("what3")
                        }
                        print("what2")
                        //Leave second async call
                        myGroup.leave()
                    }
                    print("what1")
                }
                //Leave first async call
                myGroup.leave()
                print("what4")
             }

             myGroup.notify(queue: DispatchQueue.global(qos: .background)) {
                 print("HERE I SHOULD BE DONE")
             }
             
             print("what5")
         }
        
    }

建议:在使用DispatchGroup/Asynchron调用时尽量分流。例如为每个调用使用一个函数,因为它很快就会变得非常混乱。将它们分开,然后将它们组合成一种方法,也可以更轻松地修改和/或查找错误。