I try to modify a string using data in each node I retrieve from Firebase database, and then to write a file with the modifed string (called "content").
Here is what I tried :
// 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);
Result :
"test" is shown before the forEach ends.
I found that we can do in Dart (https://groups.google.com/a/dartlang.org/forum/#!topic/misc/GHm2cKUxUDU) :
await Future.forEach
but in my case if I do : await Future.response.value.forEach (sounds a bit weird)
then I get :
Getter not found: 'response'. await Future.response.value.forEach((jsonString) async {
How to wait that forEach ends (with "content" modified) before to write the file with new content?
Any idea?
If you use for(... in )
instead of forEach
you can use 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);
});
});
}
With forEach
the calls fire away for each jsonString
immediately and inside it await
works, but forEach
has return type void
and that can't be awaited, only a Future
can.
You defined the callback for forEach as async
, which means that it runs asynchronously. In other words: the code inside of that callback runs independently of the code outside of the callback. That is exactly why print("test");
runs before the code inside of the callback.
The simplest solution is to move all code that needs information from within the callback into the callback. But there might also be a way to await all of the asynchronous callbacks, similar to how you already await
the once
call above it.
Update I got working what I think you want to do. With this 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
}
}
I can read the index, and then join the data with:
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"]);
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With