如何在map()(Flutter,Firestore)中使用异步代码 [英] How to use async code inside map() (Flutter, Firestore)

查看:33
本文介绍了如何在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 Futures.

您可以使用List< Future< Message>> 转换为 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 awaited, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆