无法在 flutter 中获取子集合和集合

Cannot get subcollection along with collection in flutter

我正在尝试从 Stream 获取带有自己的子集合的文档,但我卡住了。

这是我设置 StreamSubscription 的地方:

Future<void> _toggleOrdersHistorySubscription({FirebaseUser user}) async {
    _ordersHistorySubscription?.cancel();
    if (user != null) {
      _ordersHistorySubscription = ordersRepository
          .ordersHistoryStream(userId: user.uid)
          .listen((ordersSnapshot) {
        final List<OrderModel> tmpList = ordersSnapshot.documents.map((e) {
          // e.reference.collection("cart").getDocuments().;
          return OrderModel.orderFromSnapshot(e);
        }).toList();
        add(OrdersHistoryUpdated(ordersHistory: tmpList));
      });
    }
  }

问题是我看不到获取子集合和父文档的方法,因为 getDocuments return 是一个 Future。 谁能帮我解决这个问题?


因此,我将代码方法更新为一个单独的方法,用于在触发侦听器时检索数据,但它不能完全工作,我不明白发生了什么,也不知道为什么部分代码有效而部分无效。

List<OrderModel> _getOrdersHistory({
    @required QuerySnapshot snapshot,
  }) {
    return snapshot.documents.map((document) {
          List<OrderedProductModel> cart = [];
          List<AddressModel> addresses = [];
          document.reference.collection("cart").getDocuments().then((snapshot) {
            snapshot?.documents?.forEach((doc) {
              cart.add(OrderedProductModel.fromSnapshot(doc));
            });
          });
          document.reference
              .collection("addresses")
              .getDocuments()
              .then((snapshot) {
            snapshot?.documents?.forEach((doc) {
              addresses.add(AddressModel.addressFromJson(doc.data));
            });
          });

          final order = OrderModel.orderFromSnapshot(
            document,
            restaurantCart: cart,
          );
          return order.copyWith(
            orderAddress:
                (addresses?.isNotEmpty ?? false) ? addresses.first : null,
            sentFromAddress:
                (addresses?.isNotEmpty ?? false) ? addresses.last : null,
          );
        })
            .toList() ??
        [];
  }

作为我最初问题的替代解决方案,我在 Firestore 中创建了一个地图条目,而不是 2 个地址文档(上面设置为 orderAddress 和 sentFromAddress)的集合,对于购物车,我决定获取数据每个购物车商品都需要时。

所以我放在更新中的方法不是最后一个,但我想了解那里发生了什么,因为我不明白为什么:

  1. 为什么我执行 print(order) 时购物车显示为空;就在 return 之前,在 bloc 中它有数据;
  2. 为什么无论我怎么尝试,orderAddress 和 sentFromAddress 都是空的;

如果returns未来有什么,就这样做:

...getDocuments().then((value) => {
value is the item return here. Do something with it....
})

此外,您可能希望将您的方法拆分一些以分担责任。

如果getDocuments是一个Future函数而你需要等待它,我觉得你应该在它前面加上await。我也没有在此处粘贴的代码中看到快照状态检查。也许您已经在其他功能中检查过快照状态?使用时请确保快照已准备就绪。

简而言之:如果您从 firebase 获取异步数据,您将永远无法同步获取列表。

两个问题的答案相同:

您的时间表:

  1. 对于每个文件
    1. 创建一个空列表
    2. 启动 firebase 查询 - getDocuments()
    3. 使用 - .then((snapshot){cart.add(...)}) 订阅 returned 未来。 当文档到达时将调用此 lambda。
    4. 再订阅
    5. 将空 cart 和空 addresses 的 first/last 保存到 OrderModel
  2. 您的列表包含对空列表的间接引用
  3. 使用你的集团,一段时间过去了
  4. Firebase 完成,您的回调开始填满您的列表。

关于您的评论 stream.listen 不喜欢异步回调: 那不是真的,你只需要知道如何 async functions work。它们 运行 同步直到第一个等待,然后 return 有一个不完整的未来。如果你做真正的异步事情,你必须处理时间延迟的后果,比如改变环境或并行 运行ning 监听器。 您可以处理并行 运行 await for (T v in stream) 或者您可以使用 subscription.pause() 和 resume.