Мой асинхронный вызов возвращается до заполнения списка в цикле forEach - PullRequest
0 голосов
/ 29 июня 2018

У меня есть подпрограмма, которая получает список имен файлов с устройства, а затем читает файл (ы) для создания списка. Однако вызывающая подпрограмма всегда возвращается с нулевыми элементами. Я печатаю имена файлов, так что я знаю, что они существуют, однако, похоже, что асинхронность возвращается, прежде чем я читаю файлы. Я использовал подобный код при выполнении HTTP-вызова. Но что-то здесь заставляет подпрограмму возвращать список, даже если она еще не завершена. Возможно, возможно, что я звоню не в то время? Я звоню retrieveItems здесь:

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

Со временем у меня будет кнопка обновления, но сейчас я просто хотел бы, чтобы список заполнялся данными из файлов ...

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

1008 * вызываемая сторона *

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();
        });
      });
    }
  });

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Чтобы расширить комментарий Гюнтера относительно использования list.map(f), вот пример преобразования вызова forEach, чтобы он работал правильно.

Разбитый пример

Неправильно предполагает, что forEach будет ожидать фьючерсов:

Future<void> brokenExample(List<String> someInput) async {    
  List<String> results;

  someInput.forEach((input) async {
    String result = await doSomethingAsync(input);
    results.add(result);
  });

  return results;
}

Исправленный пример

Ожидание завершения асинхронных функций с использованием Future.wait и .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;
}
0 голосов
/ 29 июня 2018

Этот код

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;
}

возвращает список l и затем обрабатывает обратные вызовы asyc forEach(...)

Если вы измените его на

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;
}

функция не вернется до обработки всех имен файлов.

files.forEach((filename) async {

означает, что вы можете использовать await внутри обратного вызова, но forEach не заботится о том, что возвращает (filename) async {...}.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...