Асинхронная загрузка нескольких функций друг за другом
Как я могу сообщить 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
файл обнаружил бы эту проблему во время статического анализа.