I have a code that loads data from firebase, the data is not loaded immediately and I want to load the data first, and then pass the data to the delegate. To do this, I used the wait construct and the synchronous loadData function
let dateUser = await loadData(phoneNumber: phoneNumber)
According to the idea, the dateUser
variable should wait until the function returns the result, but the function returns the result immediately without waiting for the data to load
Can you tell me what the error is, I think that you need to wait inside the loadData
function, but where?
Everywhere there are examples of how to use this construction for loading JSON files, but I did not find where it would be used inside the closure
here is a sample code
struct LoadData {
let db = Firestore.firestore()
var delegate: LoadDataDelegate?
func getData(phoneNumber:String){
Task.init {
let dateUser = await loadData(phoneNumber: phoneNumber)
print("Делегат получил дату - ", dateUser)
delegate!.loadData(date: dateUser)
}
}
func loadData(phoneNumber: String) async -> TimeInterval? {
var existingUser = false /// Проверка существует ли пользователь с данным номером телефона в базе
var date: TimeInterval?
db.collection("Users").getDocuments { QuerySnapshot, Error in
if let err = Error {
print("Ошибка получения данных - \(err)")
}
for document in QuerySnapshot!.documents {
if document.documentID == phoneNumber { /// Если текущий пользователь уже был зарегестрирован
existingUser = true
date = document["dateFirstLaunch"] as? TimeInterval /// Преобразуем данные из FireBase
print("это дата ",date!)
}
}
if existingUser == false { /// Если такого пользователя не было
print("New User")
db.collection("Users").document(phoneNumber).setData(["dateFirstLaunch" : NSDate().timeIntervalSince1970]) { error in
if let err = error {
print("Ошибка записи данных в обалко - \(err)")
}
}
}
}
return date
}
}
protocol LoadDataDelegate {
func loadData(date: TimeInterval?)
}
I tried to wait inside the loadData
function, but as a result, either errors come out or nothing works
You are not await
ing any of the asynchronous operations in loadData
, so loadData
returns immediately.
You should use the async
versions of the Firebase Firestore APIs , rather than those with completion handlers.
Instead of passing a completion handler, try await
the asynchronous operations. Simply put the code in the completion handler after the try await
line, and handle the error with a catch
block.
For example:
func loadData(phoneNumber: String) async -> TimeInterval? {
do {
let querySnapshot = try await db.collection("Users").getDocuments()
for document in querySnapshot.documents {
if document.documentID == phoneNumber {
return document["dateFirstLaunch"] as? TimeInterval
}
}
} catch {
print("Ошибка получения данных - \(error)")
// I assume you want to return nil immediately in this case and not write to the document
return nil
}
print("New User")
do {
try await db.collection("Users").document(phoneNumber).setData(["dateFirstLaunch" : Date().timeIntervalSince1970])
} catch {
print("Ошибка записи данных в обалко - \(error)")
}
// I assume that in the new user case, you want to return nil
return nil
}