Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My async call is returning before list is populated in forEach loop

I have a routine which gets a list of filenames from the device, then reads the file(s) to build a list. However, the calling routine always returns with zero items. I print the filenames, so I know they exist, however, it appears that the async is returning before I read the files. I used similar code when making an HTTP call. But, something here is causing the routine to return the list even though it hasn't completed. Perhaps, it is possible that I am calling it at the wrong time? I am calling retrieveItems here:

@override   void initState() {     super.initState();     retrieveItems();   } 

Eventually I will have a refresh button, but for now I'd simply like the list to populate with the data from the files...

--------------------

Callee

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 usr = User.fromJson(json.decode(contents));     String name = usr.NameLast + ", " + usr.NameFirst;     print(name);     l.add(name);   }   return l; 

Caller

void retrieveItems() async {   LocalStorage storage = new LocalStorage();   await storage.readHeaderData().then((item) {       try {         if ((item != null ) &&(item.length >= 1)) {           setState(() {             users.clear();             _users.addAll(item);           });         } else {           setState(() {             _users.clear();             final snackbar = new SnackBar(               content: new Text('No users found.'),             );             scaffoldKey.currentState.showSnackBar(snackbar);           });         }       } on FileNotFoundException catch (e) {         print(e.toString()); //For debug only         setState(() {           _users.clear();         });       });     }   }); 
like image 670
Jerry Avatar asked Jun 29 '18 17:06

Jerry


People also ask

Why Async does not work in forEach?

forEach expects a synchronous function and won't do anything with the return value. It just calls the function and on to the next. for...of will actually await on the result of the execution of the function.

Does async work in forEach?

forEach is not designed for asynchronous code. (It was not suitable for promises, and it is not suitable for async-await.) For example, the following forEach loop might not do what it appears to do: const players = await this.

How do I use async in flutter?

You can declare a synchronous function with async without an error. An async keyword would try to help you turn your function into asynchronous most of the time by enforcing the return type of your function to Future . You will get the following error if the return type is not Future .


1 Answers

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.

like image 55
Günter Zöchbauer Avatar answered Oct 11 '22 10:10

Günter Zöchbauer