如何在map()(Flutter,Firestore)中使用异步代码 [英] How to use async code inside map() (Flutter, Firestore)
问题描述
我正在使用Flutter和Firestore插件开发群聊应用.从数据库中获取数据并将快照转换为消息列表"非常正常.但是现在我想将数据库中的uid转换为用户名(uid及其用户名保存在db中).这是我的代码:
I am working on a group chat app with Flutter and the Firestore Plugin. Getting the data from the database and converting the snapshot into a List of Messages works totally fine. But now I want to convert the uid from the database into the username (the uids and their usernames are saved in the db). This is my code:
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()内部运行此异步代码.
The problem is in this line, because I cannot run this async code inside of the map().
String username = await getUsernameByUID(doc.data["uid"]);
是否有解决此问题的解决方案?预先感谢.
Is there a solution to fix this? Thanks in advance.
推荐答案
async
函数必须返回 Future
,因此将 async
关键字添加到您的回调意味着您的 List.map()
调用现在必须返回 Future
s的 List
.
async
functions must return a Future
, so adding async
keyword to your callback means that your List.map()
call must now return a List
of Future
s.
您可以使用 List< Message>
.org/stable/2.2.0/dart-async/Future/wait.html"rel =" noreferrer> Future.wait
:
You can convert a List<Future<Message>>
to a List<Message>
by using 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
,所以现在 _messagesFromSnapshot
也是 async
.异步具有传染性,因此会影响 _messagesFromSnapshot
的所有调用方.
Of course, Future.wait
returns a Future
and must be await
ed, so now _messagesFromSnapshot
must be async
as well. Asynchrony is contagious, and that then would affect any callers of _messagesFromSnapshot
.
由于 messages
getter返回 Stream
并且已经异步,所以我相信您可以使用
Since the messages
getter returns a Stream
and is already asynchronous, I believe that you instead can use Stream.asyncMap
:
Stream<List<Message>> get messages {
return messagesCollection
.orderBy("time")
.snapshots()
.asyncMap(_messagesFromSnapshot);
}
这篇关于如何在map()(Flutter,Firestore)中使用异步代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!