Flutter - Dart:等待 forEach 结束

Jul*_*ien 5 dart firebase firebase-realtime-database flutter

我尝试使用从 Firebase 数据库中检索到的每个节点中的数据修改字符串,然后使用修改后的字符串(称为“内容”)编写一个文件。

这是我尝试过的:

// Retrieve initial content from Firebase storage
var data = await FirebaseStorage.instance.ref().child("...").getData(1048576);
var content = new String.fromCharCodes(data);

// Edit content with each node from Firebase database
final response = await FirebaseDatabase.instance.reference().child('...').once();
response.value.forEach((jsonString) async {
     ...
     // cacheManager.getFile returns a Future<File>
     cacheManager.getFile(signedurl).then((file){ 
         // Modify content
         content=content.replaceAll('test',file.path);
     });
});

// Finally write the file with content
print("test");
final localfile = File('index.html');
await localfile.writeAsString(content);
Run Code Online (Sandbox Code Playgroud)

结果 :

“test”显示在 forEach 结束之前。

我发现我们可以在 Dart ( https://groups.google.com/a/dartlang.org/forum/#!topic/misc/GHm2cKUxUDU ) 中做到:

等待 Future.forEach

但在我的情况下,如果我这样做:await Future.response.value.forEach(听起来有点奇怪)

然后我得到:

未找到 Getter:“响应”。等待 Future.response.value.forEach((jsonString) async {

在用新内容写入文件之前,如何等待 forEach 结束(修改了“内容”)?

任何的想法?

Gün*_*uer 16

如果你使用for(... in )而不是forEach你可以使用async/await

Future someMethod() async {
  ...

  for(final jsonString in response.value) {
     ...
     // cacheManager.getFile returns a Future<File>
     cacheManager.getFile(signedurl).then((file){ 
         // Modify content
         content=content.replaceAll('test',file.path);
     });
  });
}
Run Code Online (Sandbox Code Playgroud)

随着forEach每个调用jsonString立即被触发并且在它内部await工作,但forEach具有返回类型void并且不能等待,只有一个Future可以。


Fra*_*len 8

您将 forEach 的回调定义为async,这意味着它异步运行。换句话说:回调内部的代码独立于回调外部的代码运行。这正是为什么print("test");在回调内部的代码之前运行的原因。

最简单的解决方案是将所有需要信息的代码从回调中移到回调中。但是也可能有一种方法来等待所有异步回调,类似于您已经awaitonce它上面调用的方式。

更新我开始做我认为你想做的事情。使用这个 JSON:

{
  "data" : {
    "key1" : {
      "created" : "20181221T072221",
      "name" : "I am key1"
    },
    "key2" : {
      "created" : "20181221T072258",
      "name" : "I am key 2"
    },
    "key3" : {
      "created" : "20181221T072310",
      "name" : "I am key 3"
    }
  },
  "index" : {
    "key1" : true,
    "key3" : true
  }
}
Run Code Online (Sandbox Code Playgroud)

我可以读取索引,然后加入数据:

final ref = FirebaseDatabase.instance.reference().child("/53886373");
final index = await ref.child("index").once();
List<Future<DataSnapshot>> futures = [];
index.value.entries.forEach((json) async {
  print(json);
  futures.add(ref.child("data").child(json.key).once());
});
Future.wait(futures).then((List<DataSnapshot> responses) {
  responses.forEach((snapshot) {
    print(snapshot.value["name"]);
  });
});
Run Code Online (Sandbox Code Playgroud)