我正在使用Flutter和Firestore插件开发群聊应用。从数据库中获取数据并将快照转换为“消息列表”非常正常。但是现在我想将数据库中的uid转换为用户名(uid及其用户名保存在db中)。这是我的代码:
final CollectionReference messagesCollection =
Firestore.instance.collection('messages');
final CollectionReference usersCollection =
Firestore.instance.collection('users');
Future<String> getUsernameByUID(String _uid) async {
String username =
await usersCollection.document(uid).get().then((querySnapshot) {
return (querySnapshot.data["username"]);
});
return username;
}
List<Message> _messagesFromSnapshot(QuerySnapshot snapshot){
return snapshot.documents.map((doc) {
String username = await getUsernameByUID(doc.data["uid"]);
return Message(
text: doc.data["text"] ?? "",
username: username ?? "",
time: doc.data["time"] ?? "",
);
}).toList();
}
Stream<List<Message>> get messages {
return messagesCollection
.orderBy("time")
.snapshots()
.map(_messagesFromSnapshot);
}
问题出在这一行,因为我无法在map()内部运行此异步代码。
String username = await getUsernameByUID(doc.data["uid"]);
是否有解决此问题的解决方案?预先感谢。
答案 0 :(得分:1)
您需要的是Future.forEach方法。它会遍历列表,并等待所有异步方法完成,然后再继续执行列表中的下一项。
Future<List<Message>> _messagesFromSnapshot(QuerySnapshot snapshot) async {
List<Message> _messages = [];
await Future.forEach(snapshot.documents, (doc) async {
String username = await getUsernameByUID(doc.data["uid"]);
_messages.add(
Message(
text: doc.data["text"] ?? "",
username: username ?? "",
time: doc.data["time"] ?? "",)
);
});
return _messages;
}
下面是一个示例dartpad
答案 1 :(得分:1)
async
函数必须返回一个Future
,因此在您的回调中添加async
关键字意味着您的List.map()
调用现在必须返回一个{{ 1}} s。
您可以使用Future.wait
将List
转换为Future
:
List<Future<Message>>
当然,List<Message>
返回Future<List<Message>> _messagesFromSnapshot(QuerySnapshot snapshot) async {
var futures = snapshot.documents.map((doc) async {
String username = await getUsernameByUID(doc.data["uid"]);
return Message(
text: doc.data["text"] ?? "",
username: username ?? "",
time: doc.data["time"] ?? "",
);
});
return await Future.wait(futures);
}
,并且必须进行Future.wait
,因此现在Future
也必须是await
。异步具有传染性,因此会影响_messagesFromSnapshot
的所有调用方。
由于async
的getter返回_messagesFromSnapshot
并且已经是异步的,因此我相信您可以使用Stream.asyncMap
:
messages