【问题标题】:Firebase cloud function ends before returnFirebase 云功能在返回前结束
【发布时间】:2022-01-15 00:08:29
【问题描述】:

我制作了一个 SwiftUI 应用程序,它通过多个 Firebase 云函数获取其 Firestore 数据。我想要获取的 Firestore 文档的结构如下:

Firestore structure

现在,我想调用一个名为“getLocationObjectsFromUser”的云函数,它从用户相关集合locationIds 中获取所有LocationIds。然后,我想从具有特定 locationId 的位置文档中获取所有数据,包括集合“UserIds”。

我尝试过类似的方法,但在这种情况下,firebase 函数日志总是告诉我该函数已完成,尽管它还没有完成获取所有数据。正因为如此,我的 swift App 没有获得任何数据。我怎样才能返回我想要的所有数据?

功能代码:

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.
        }
    }

【问题讨论】:

    标签: swift firebase asynchronous google-cloud-firestore google-cloud-functions


    【解决方案1】:

    问题出在最后一行:

    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。

    【讨论】:

    • 感谢您的回复。我试过你的代码,关于firebase的一切都很好(数据返回后函数完成)。我仍然有返回的数据没有到达我的应用程序的问题。该应用程序调用我的函数,但没有任何反应..
    猜你喜欢
    • 2021-10-26
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 2020-05-18
    • 2020-03-21
    • 2018-08-12
    • 2018-06-03
    • 2020-06-09
    相关资源
    最近更新 更多