提问人:David 提问时间:9/29/2022 更新时间:9/29/2022 访问量:771
等待完成处理程序完成后再返回
Wait for completion handler to finish before returning
问:
func checkUsername(username: String) -> Bool {
var avalible = true
Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() {
print("exists")
avalible = false
}
})
return available
}
我正在尝试检查用户名是否存在。
我已经尝试了多种方法,但似乎该函数总是在完成处理程序完成之前返回,并且即使用户名已被占用,也总是给出相同的输出 (true)。
是否有人知道如何在返回“可用”变量之前先“等待”完成处理程序完成?
带有答案的解释会很好。
谢谢。
答:
0赞
Erik Terwan
9/29/2022
#1
这是因为 Firebase 操作是异步的,您不能简单地将其转换为同步操作而不阻塞线程。
在不使用新的 async/await 语法的情况下,解决此问题的正确方法是自己使用完成处理程序。
func checkUsername(username: String, completion: @escaping (Bool) -> ()) {
Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value) { snapshot in
completion(!snapshot.exists())
}
}
// To use:
checkUsername(username: "foo") { exists in
print("exists? ", exists)
}
评论
0赞
Duncan C
9/29/2022
人们不会简单地从异步函数返回结果:imgflip.com/i/6v4w6c
2赞
vadian
9/29/2022
#2
不能从异步任务返回某些内容。您的代码(带有固定的拼写错误)甚至在数据库请求启动之前就返回。true
也许有一个原生的 async/await 版本,但无论如何你都可以使用observeSingleEvent
Continuation
func checkUsername(username: String) async -> Bool {
return await withCheckedContinuation { continuation in
Database.database().reference().child("usernames").child(username).observeSingleEvent(of: .value, with: { snapshot in
continuation.resume(returning: !snapshot.exists())
})
}
}
并称它为
Task {
let isAvailable = await checkUsername(username: "Foo")
}
评论
0赞
David
9/29/2022
谢谢,我以前确实尝试过这个,但有两个不同的延续,这就是为什么我感到困惑并且它不起作用。
评论