无法在 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)的集合,对于购物车,我决定获取数据每个购物车商品都需要时。
所以我放在更新中的方法不是最后一个,但我想了解那里发生了什么,因为我不明白为什么:
- 为什么我执行 print(order) 时购物车显示为空;就在 return 之前,在 bloc 中它有数据;
- 为什么无论我怎么尝试,orderAddress 和 sentFromAddress 都是空的;
如果returns未来有什么,就这样做:
...getDocuments().then((value) => {
value is the item return here. Do something with it....
})
此外,您可能希望将您的方法拆分一些以分担责任。
如果getDocuments
是一个Future函数而你需要等待它,我觉得你应该在它前面加上await
。我也没有在此处粘贴的代码中看到快照状态检查。也许您已经在其他功能中检查过快照状态?使用时请确保快照已准备就绪。
简而言之:如果您从 firebase 获取异步数据,您将永远无法同步获取列表。
两个问题的答案相同:
您的时间表:
- 对于每个文件
- 创建一个空列表
- 启动 firebase 查询 -
getDocuments()
- 使用 -
.then((snapshot){cart.add(...)})
订阅 returned 未来。
当文档到达时将调用此 lambda。
- 再订阅
- 将空
cart
和空 addresses
的 first/last 保存到 OrderModel
- 您的列表包含对空列表的间接引用
- 使用你的集团,一段时间过去了
- Firebase 完成,您的回调开始填满您的列表。
关于您的评论 stream.listen 不喜欢异步回调:
那不是真的,你只需要知道如何 async functions work。它们 运行 同步直到第一个等待,然后 return 有一个不完整的未来。如果你做真正的异步事情,你必须处理时间延迟的后果,比如改变环境或并行 运行ning 监听器。
您可以处理并行 运行 await for (T v in stream)
或者您可以使用 subscription.pause() 和 resume.
我正在尝试从 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)的集合,对于购物车,我决定获取数据每个购物车商品都需要时。
所以我放在更新中的方法不是最后一个,但我想了解那里发生了什么,因为我不明白为什么:
- 为什么我执行 print(order) 时购物车显示为空;就在 return 之前,在 bloc 中它有数据;
- 为什么无论我怎么尝试,orderAddress 和 sentFromAddress 都是空的;
如果returns未来有什么,就这样做:
...getDocuments().then((value) => {
value is the item return here. Do something with it....
})
此外,您可能希望将您的方法拆分一些以分担责任。
如果getDocuments
是一个Future函数而你需要等待它,我觉得你应该在它前面加上await
。我也没有在此处粘贴的代码中看到快照状态检查。也许您已经在其他功能中检查过快照状态?使用时请确保快照已准备就绪。
简而言之:如果您从 firebase 获取异步数据,您将永远无法同步获取列表。
两个问题的答案相同:
您的时间表:
- 对于每个文件
- 创建一个空列表
- 启动 firebase 查询 -
getDocuments()
- 使用 -
.then((snapshot){cart.add(...)})
订阅 returned 未来。 当文档到达时将调用此 lambda。 - 再订阅
- 将空
cart
和空addresses
的 first/last 保存到OrderModel
- 您的列表包含对空列表的间接引用
- 使用你的集团,一段时间过去了
- Firebase 完成,您的回调开始填满您的列表。
关于您的评论 stream.listen 不喜欢异步回调:
那不是真的,你只需要知道如何 async functions work。它们 运行 同步直到第一个等待,然后 return 有一个不完整的未来。如果你做真正的异步事情,你必须处理时间延迟的后果,比如改变环境或并行 运行ning 监听器。
您可以处理并行 运行 await for (T v in stream)
或者您可以使用 subscription.pause() 和 resume.