我制作了一个SwiftUI应用程序,它通过多个Firebase云函数获取Firestore数据。我想要得到的Firestore文档的结构如下:
防火仓库结构
现在,我想调用一个名为"getLocationObjectsFromUser";其从用户相关集合LocationIds中获取所有LocationIds然后,我想从具有特定locationId的位置文档中获取所有数据,包括集合";用户ID";。
我尝试过这样的方法,但在这种情况下,firebase函数日志总是告诉我函数已经完成,尽管它还没有完成获取所有数据。正因为如此,我的swift应用程序没有得到任何数据。我如何才能返回我想要的所有数据?
功能代码:
exports.getLocationObjectsFromUser =
functions.https.onCall((data, context) => {
const locations = [];
let userIds = [];
return userRef
.doc(data.userId)
.collection("locationIds")
.where("status", "==", true)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
return locationRef
.doc(doc.id)
.get()
.then((locationDoc) => {
return locationRef
.doc(locationDoc.id)
.collection("userIds")
.get()
.then((querySnapshot1) => {
querySnapshot1.forEach((doc1) => {
userIds.push(doc1.id);
});
const object = {...locationDoc.data(), userIds};
locations.push(object);
userIds = [];
// if statement to avoid return before function has finished running
if (querySnapshot.size == locations.length) {
return {locations: locations};
}
});
});
});
});
});
Swift代码:
func getLocationObjectsFromUser(_ user_id: String, onSuccess: @escaping ([LocationModel]) -> Void, onError: @escaping(_ error: String?) -> Void) {
let dic = ["userId" : user_id] as [String : Any]
self.functions.httpsCallable("getLocationObjectsFromUser").call(dic) { (result, error) in
if let error = error as NSError? {
print("ERROR")
print(error)
onError(error.localizedDescription)
}
if let data = result?.data as? [String: Any] {
print("DATA")
print(data)
// Later on i want to return the LocationModel with something like this: onSuccess(Data).
}
// i do not get any data after calling the function.
}
}
问题是这里的最后一行:
return userRef
.doc(data.userId)
.collection("locationIds")
.where("status", "==", true)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
return locationRef...
由于您在querySnapshot
中循环遍历文档,因此其中有多个调用return locationRef...
,并且您没有代码确保在Cloud Function终止之前完成所有这些读取。
每当您需要在代码中等待同一级别上的多个操作时,您的答案是使用Promise.all
:
return userRef
.doc(data.userId)
.collection("locationIds")
.where("status", "==", true)
.get()
.then((querySnapshot) => {
return Promise.all(querySnapshot.docs.map((doc) => {
return locationRef...
所以变化:
我们返回一个
Promise.all()
,它只有在完成所有嵌套读取后才能解析。我们使用
querySnapshot.docs.map
而不是querySnapshot.forEach
,这样我们就得到了一个传递给Promise.all
的promise数组。