[英]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
}
I'm trying to check if a username exists.我正在尝试检查用户名是否存在。
I've already tried multiple things, but it seems like the function always returns before the completion handler even finishes and always gives the same output (true) even if the username is already taken.我已经尝试了多种方法,但似乎 function 总是在完成处理程序完成之前返回,并且即使用户名已被使用,也总是给出相同的 output (true)。
Does somebody have an idea how to „wait“ for the completion handler first to finish before returning the „available“ variable?有人知道如何在返回“可用”变量之前先“等待”完成处理程序完成吗?
An explanation with the answer would be excellent.有答案的解释会很好。
Thanks.谢谢。
You cannot return something from an asynchronous task.您不能从异步任务中返回一些东西。 Your code – with fixed typos – returns
true
even before the database request has been started.您的代码 - 带有固定拼写错误 - 甚至在数据库请求开始之前就返回
true
。
Maybe there is a native async/await version of observeSingleEvent
but in any case you can use a Continuation
也许有一个原生的 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())
})
}
}
And call it并称之为
Task {
let isAvailable = await checkUsername(username: "Foo")
}
This is because the Firebase operation is asynchronous, you cannot simply turn that into a synchronous operation without blocking the thread.这是因为 Firebase 操作是异步的,您不能简单地将其转换为同步操作而不阻塞线程。
Have a look at How could I create a function with a completion handler in Swift?看看我如何在 Swift 中创建一个带有完成处理程序的 function?
The correct way to approach this, without the use of the new async/await syntax, is to use a completion handler yourself.在不使用新的 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)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.