使用嵌套异步 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调用时尽量分流。例如为每个调用使用一个函数,因为它很快就会变得非常混乱。将它们分开,然后将它们组合成一种方法,也可以更轻松地修改和/或查找错误。
我对异步函数比较陌生,我知道 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调用时尽量分流。例如为每个调用使用一个函数,因为它很快就会变得非常混乱。将它们分开,然后将它们组合成一种方法,也可以更轻松地修改和/或查找错误。