My async call is returning before list is populated in forEach loop
This code
Future<List<String>> readHeaderData() async { List<String> l = new List(); List<String> files = await readHeaders(); // Gets filenames files.forEach((filename) async { final file = await File(filename); String contents = await file.readAsString(); User user = User.fromJson(json.decode(contents)); String name = user.NameLast + ", " + user.NameFirst; print(name); l.add(name); } return l;}
returns the list l
and then processes the asyc forEach(...)
callbacks
If you change it to
Future<List<String>> readHeaderData() async { List<String> l = new List(); List<String> files = await readHeaders(); // Gets filenames for(var filename in files) { /// <<<<==== changed line final file = await File(filename); String contents = await file.readAsString(); User user = User.fromJson(json.decode(contents)); String name = user.NameLast + ", " + user.NameFirst; print(name); l.add(name); } return l;}
the function will not return before all filenames are processed.
files.forEach((filename) async {
means that you can use await
inside the callback, but forEach
doesn't care about what (filename) async {...}
returns.
Also possible
await Future.forEach(yourList, (T elem) async { ...async staff });
To expand on Günter's comment regarding using list.map(f)
, here's an example of converting a forEach
call so that it works correctly.
Broken example
Incorrectly assumes forEach
will wait on futures:
Future<void> brokenExample(List<String> someInput) async { List<String> results; someInput.forEach((input) async { String result = await doSomethingAsync(input); results.add(result); }); return results;}
Corrected example
Waits on the async functions to complete, using Future.wait
and .map()
:
Future<void> correctedExample(List<String> someInput) async { List<String> results; await Future.wait(someInput.map((input) async { String result = await doSomethingAsync(input); results.add(result); })); return results;}