Асинхронная загрузка нескольких функций друг за другом

Как я могу сообщить Flutter, что нужно дождаться завершения одной функции (и, следовательно, будущего), пока не будет вызвана следующая функция? Кажется, что сама функция load() завершается до завершения loadFeed() Future, как я могу это исправить?

Вот мой текущий код:

      ValueNotifier<List> data = ValueNotifier([]);
ValueNotifier<bool> loading = ValueNotifier(true);

loadAll() async {
  await load(0, 'url1');
  print("0 finished");
  await load(1, 'url2');
  print("1 finished");
  await load(2, 'url3');
  print("2 finished");
}

load(int categoryIndex, String _url) async {
  loadFeed(_url).then((result) {
    if (null == result || result.toString().isEmpty) {
      print("error");
      return;
    }
    data.value = [[],[],[],];
    for (var i = 0; i < result.items.length; i++) {
      data.value[categoryIndex].add(result.items[i]);
    }
    data.notifyListeners();
  });
}

Future<RssFeed> loadFeed(String _url) async {
  loading.value = true;
  try {
    final client = http.Client();
    final response = await client.get(Uri.parse(_url));

    return RssFeed.parse(response.body);
  } catch (e) {
    print("error");
  } finally {
    loading.value = false;
  }
  return null;
}

2 ответа

Решение

В будущих функциях вы можете использовать whencomplete, из документации:

«WhenComplete», регистрирует функцию, которая будет вызываться по завершении этого future-объекта.

Функция [действие] вызывается, когда это future завершается, независимо от того, выполняется ли это со значением или с ошибкой.

Это асинхронный эквивалент блока «finally».

  • Изменять load в будущую функцию и добавьте возвращаемое значение, чтобы дротик знал, что все готово, например:

            Future load(int categoryIndex, String _url) async {
       loadFeed(_url).then((result) {
         if (null == result || result.toString().isEmpty) {
           print("error");
           return;
         }
         data.value = [[],[],[],];
         for (var i = 0; i < result.items.length; i++) {
           data.value[categoryIndex].add(result.items[i]);
         }
        return data.notifyListeners(); //add a return here, to tell dart that this function is done.
       });
     }
    
  • Измените свой loadAll в это:

            loadAll() async { 
    await load(0, 'url1')
    .whenComplete(() async => await load(1, 'url2')
    .whenComplete(() async => await load(2, 'url3')));}
    

Похоже, что load() сама функция завершается до того, как loadFeed() Будущее кончено, как я могу это исправить?

Это именно то, что не так. Вы делаете:

      
load(int categoryIndex, String _url) async {
  loadFeed(_url).then((result) {
    // ... bunch of code...
  });
}

Ваш load вызовы функций loadFeed, регистрирует Future.thenобратного вызова, игнорирует вновь возвращенное и синхронно возвращается к вызывающему после регистрации обратного вызова. Он не используется для ожидания завершения и не возвращает вызывающему объекту, чтобы он мог дождаться завершения.

Это намного проще, если вы используете async/ await вместо того, чтобы смешивать его с сырым Future API:

      Future<void> load(int categoryIndex, String _url) async {
  var result = await loadFeed(_url);
  // ... bunch of code...
}

Кроме того, включение unawaited_futuresворсинки в твоемanalysis_options.yamlфайл обнаружил бы эту проблему во время статического анализа.

Другие вопросы по тегам