从 Firebase firestore 查询数据时如何在流内等待

发布于 2025-01-11 14:32:04 字数 1205 浏览 0 评论 0 原文

对于上下文,我使用 Getx 状态管理进行 flutter,并且需要在我的 Rx> 对象上调用 list.bindStream(availabilityStream()) 。 这是我的availabilityStream方法

  static Stream<List<Availability>> availabilityStream() {
    return FirebaseFirestore.instance
        .collection('availability')
        .where('language',
            isEqualTo: GetStorageController.instance.language.value)
        .snapshots()
        .map((QuerySnapshot query) {
      List<Availability> results = [];
      for (var availablity in query.docs) {
        availablity["cluster"].get().then((DocumentSnapshot document) {
          if (document.exists) {
            print("Just reached here!");
            //! Ignore doc if cluster link is broken
            final model = Availability.fromDocumentSnapshot(
                availabilityData: availablity, clusterData: document);
            results.add(model);
          }
        });
      }
      print("result returned");
      return results;
    });
  } 

,我的可用性集合上的集群字段是另一个集合的引用字段。这里的问题是我需要等待 .get() 调用我的 firestore 或函数在返回数据之前返回。我无法在 map 函数或 Stream 的返回类型内等待变化。那么我如何在这里等待我的函数调用呢?

For context I'm using Getx state management for flutter and i need to call list.bindStream(availabilityStream()) on my Rx<List<Availability>> object.
here is my availabilityStream method

  static Stream<List<Availability>> availabilityStream() {
    return FirebaseFirestore.instance
        .collection('availability')
        .where('language',
            isEqualTo: GetStorageController.instance.language.value)
        .snapshots()
        .map((QuerySnapshot query) {
      List<Availability> results = [];
      for (var availablity in query.docs) {
        availablity["cluster"].get().then((DocumentSnapshot document) {
          if (document.exists) {
            print("Just reached here!");
            //! Ignore doc if cluster link is broken
            final model = Availability.fromDocumentSnapshot(
                availabilityData: availablity, clusterData: document);
            results.add(model);
          }
        });
      }
      print("result returned");
      return results;
    });
  } 

the cluster field on my availability collection is a reference field to another collection. The problem here is i need to await the .get() call to my firestore or the function returns before the data gets returned. I can't await inside the map function or the return type of Stream<List> changes. so how can i await my function call here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

画离情绘悲伤 2025-01-18 14:32:04

根据我从评论中得到的建议,我使用 Stream.asyncMap 来等待所有网络调用 future 完成。

这是我更新的存储库

class AvailabilityRepository {
  static Future<Availability> getAvailabilityAndCluster(
      QueryDocumentSnapshot availability) async {
    return await availability["cluster"]
        .get()
        .then((DocumentSnapshot document) {
      if (document.exists) {
        //! Ignore doc if cluster link is broken
        final model = Availability.fromDocumentSnapshot(
            availabilityData: availability, clusterData: document);
        return model;
      }
    });
  }


  static Stream<List<Availability>> availabilityStream() {
    return FirebaseFirestore.instance
        .collection('availability')
        .where('language',
            isEqualTo: GetStorageController.instance.language.value)
        .snapshots()
        .asyncMap((snapshot) => Future.wait(
            snapshot.docs.map((e) => getAvailabilityAndCluster(e))));
  }
}

我认为它的工作原理是,正常的 .map 函数从 getAvailabilityAndCluster() 方法返回多个承诺,然后所有异步执行的进程都被放入 Future.wait() 中,这是一个等待的大承诺里面的所有承诺都要完成。然后将其传递给 .asyncMap() ,等待 Future.wait() 完成,然后再继续其结果。

using the advice i got from the comments I've used Stream.asyncMap to wait for all my network call futures to complete.

Here is my updated Repository

class AvailabilityRepository {
  static Future<Availability> getAvailabilityAndCluster(
      QueryDocumentSnapshot availability) async {
    return await availability["cluster"]
        .get()
        .then((DocumentSnapshot document) {
      if (document.exists) {
        //! Ignore doc if cluster link is broken
        final model = Availability.fromDocumentSnapshot(
            availabilityData: availability, clusterData: document);
        return model;
      }
    });
  }


  static Stream<List<Availability>> availabilityStream() {
    return FirebaseFirestore.instance
        .collection('availability')
        .where('language',
            isEqualTo: GetStorageController.instance.language.value)
        .snapshots()
        .asyncMap((snapshot) => Future.wait(
            snapshot.docs.map((e) => getAvailabilityAndCluster(e))));
  }
}

How i think this works is that the normal .map function returns multiple promises form the getAvailabilityAndCluster() method then all of the processes that execute asynchronously are all put to Future.wait() which is one big promise that waits all the promises inside it to complete. Then this is passed onto .asyncMap() which waits for the Future.wait() to complete before continuing with its result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文