我正在使用 Flutter 和 Firestore 插件开发群聊应用。从数据库中获取数据并将快照转换为消息列表完全可以。但现在我想将数据库中的 uid 转换为用户名(uid 及其用户名保存在数据库中)。这是我的代码:
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"]);
有解决办法吗?提前致谢。
最佳答案
async
函数必须返回 Future
, 所以加入 async
您的回调关键字意味着您的 List.map()
现在调用必须返回 List
的 Future
您可以转换 List<Future<Message>>
到 List<Message>
通过使用 Future.wait
:
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
ed,所以现在_messagesFromSnapshot
必须是 async
以及。异步是会传染的,然后会影响 _messagesFromSnapshot
的所有调用者.
自 messages
getter 返回一个 Stream
并且已经是异步的,我相信你可以改用 Stream.asyncMap
:
Stream<List<Message>> get messages {
return messagesCollection
.orderBy("time")
.snapshots()
.asyncMap(_messagesFromSnapshot);
}
关于firebase - 如何在 map() 中使用异步代码(Flutter、Firestore),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58978730/