【问题标题】:Flutter Web (Beta), Dart, Can't get asynchronous Future function to finish - with JSON Firestore wrapper plugin - asyc, await, FutureFlutter Web(Beta),Dart,无法完成异步 Future 函数 - 使用 JSON Firestore 包装器插件 - asyc、await、Future
【发布时间】:2020-05-31 22:44:51
【问题描述】:

我正在用 Flutter 编写一个网络应用程序(Flutter web 在 beta 通道上可用),而官方的、Google 支持的 Firebase 库不支持 web 版本的 Flutter。

我正在使用一个开源插件(这令人难以置信),它充当 Firebase 的 JSON 端点功能的包装器。 插件:https://pub.dev/packages/firebase

Future<List<Item>> pullItems(int zip, String key, int index) async {
    List<Item> itemList = [];
    final ref = store.collection("vendors-global").doc("usa").collection(zip.toString()).doc(key).collection("items");
    int i = 0;
    ref.onSnapshot.listen((querySnapshot) {
      final int snapSize = querySnapshot.size;
    querySnapshot.forEach((field) {
      var item = field.data();
      print(key + " : " + field.id);     //this prints all the items in ea. key, for debugg
      Item itemObject = new Item(item['name']);
      itemList.add(itemObject);
      i++;
      if (i == snapSize) { //this counter is how I triggered this function off after a
                     //similar function before it finished, where the parent keys came from.
        return itemList;
      }
      });
    });
  return itemList;
}

问题似乎在于 .onSnapshot.listen((querySnapshot),特别是 .listen,它是一个开放的连接。我已经看到在项目列表中定义的地方这样做了对 Firestore 的单行调用,以 await 语句开头,以 .map(()..).toList() 结尾。但它使用的是标准的 google API,它似乎还有更多灵活性。

Future<List<Item>> loadItems() async {
      final List<Item> itemList = (await Firestore.instance.collection('items').getDocuments()).documents.map((snapshot) => Item(doc['kode'], doc['name'])).toList();
      return itemList;
    }

实际问题是这个future函数立即返回空白List itemList = [];由于底部返回。但是,如果我删除底部返回,它会引发警告并且不会在那时计算。

有没有办法使用 .onSnapshot 监听功能遍历集合中的多个文档,并将它们作为列表返回?

非常感谢您的任何意见,这让我沮丧了 10 多个小时

【问题讨论】:

  • for each 中的return 语句没有达到您的预期。它只是从您作为 for each 的参数传递的闭包函数返回,而不是封闭函数。将 for each 重构为像 for (var field in querySnapshot) { 这样的普通 for 循环,然后 return 语句将按预期工作。

标签: firebase asynchronous flutter dart google-cloud-firestore


【解决方案1】:

你需要的是使用Completer ...如果你熟悉的话,这就像javascript中的promise deferal一样。看看吧:

Future<List<Item>> pullItems(int zip, String key, int index) {
    Completer<List<Item>> completer = Completer();
    List<Item> itemList = [];
    final ref = store.collection("vendors-global").doc("usa").collection(zip.toString()).doc(key).collection("items");
    int i = 0;
    ref.onSnapshot.listen((querySnapshot) {
      final int snapSize = querySnapshot.size;
    querySnapshot.forEach((field) {
      var item = field.data();
      print(key + " : " + field.id);     //this prints all the items in ea. key, for debugg
      Item itemObject = new Item(item['name']);
      itemList.add(itemObject);
      i++;
      if (i == snapSize) { //this counter is how I triggered this function off after a
                     //similar function before it finished, where the parent keys came from.
        completer.complete(itemList);
      }
      });
    });
  return completer.future;
}

请注意我是如何从函数末尾删除async 的。如果函数内部使用了任何await 调用,async 会自动为您创建Future&lt;List&lt;Item&gt;&gt;。由于您使用的是回调而不是await,那么您应该只使用Completer 来为您处理您的未来。它返回未来,并在调用completer.complete(...) 时触发任何等待其“完成”的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-19
    • 2021-03-04
    • 2020-12-21
    • 2020-06-18
    • 2021-08-27
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    相关资源
    最近更新 更多