Firebase 云函数在 return 之前结束
Firebase cloud function ends before return
我制作了一个 SwiftUI 应用程序,它通过多个 Firebase 云函数获取其 Firestore 数据。我要获取的 Firestore 文档的结构如下:
Firestore structure
现在,我想调用一个名为“getLocationObjectsFromUser”的云函数,它从用户相关集合 locationIds 中获取所有 LocationIds。然后,我想从具有特定 locationId 的位置文档中获取所有数据,包括集合“UserIds”。
我试过类似的方法,但在这种情况下,firebase 函数日志总是告诉我函数已经完成,尽管它还没有完成获取所有数据。因此,我的 swift 应用程序没有获取任何数据。我如何才能 return 我想要的所有数据?
函数代码:
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...
所以变化:
我们 return 一个 Promise.all()
只有在所有嵌套读取完成后才解析。
我们使用 querySnapshot.docs.map
而不是 querySnapshot.forEach
,这样我们就可以得到一组要传递给 Promise.all
的承诺。
我制作了一个 SwiftUI 应用程序,它通过多个 Firebase 云函数获取其 Firestore 数据。我要获取的 Firestore 文档的结构如下:
Firestore structure
现在,我想调用一个名为“getLocationObjectsFromUser”的云函数,它从用户相关集合 locationIds 中获取所有 LocationIds。然后,我想从具有特定 locationId 的位置文档中获取所有数据,包括集合“UserIds”。
我试过类似的方法,但在这种情况下,firebase 函数日志总是告诉我函数已经完成,尽管它还没有完成获取所有数据。因此,我的 swift 应用程序没有获取任何数据。我如何才能 return 我想要的所有数据?
函数代码:
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...
所以变化:
我们 return 一个
Promise.all()
只有在所有嵌套读取完成后才解析。我们使用
querySnapshot.docs.map
而不是querySnapshot.forEach
,这样我们就可以得到一组要传递给Promise.all
的承诺。