#dart #future
#dart #будущее
Вопрос:
Итак, у меня есть список файлов, и мне нужно запустить функцию для каждого элемента списка. По сути, я хочу сделать что-то вроде этого:
for(File file in files) {
functionThatReturnsAFuture(file);
}
Но, очевидно, это не сработает, поскольку функция, которая возвращает Future, срабатывает асинхронно. Является ли мой единственный вариант чем-то вроде этого?
List<File> files = new List<File>();
// Add files somewhere
Future processFile(int i) {
return new Future.sync(() {
//Do stuff to the file
if(files.length>i 1) {
return processFile(i 1);
}
});
}
processFile(0);
Редактировать:
Я полагаю, что важно больше контекста. Конечная цель — объединить несколько файлов в один объект JSON для отправки на сервер. Объект FileReader использует события для выполнения чтения, поэтому я использовал завершитель для создания функции-оболочки, которая обеспечивает будущее. Я мог бы позволить всем этим запускаться асинхронно, а затем запускать событие, которое отправляет его, когда все они будут выполнены, но это сравнительно большая настройка по сравнению с циклом for-each, который заставляет все это работать (если таковой существует, во всяком случае). Основная проблема заключается в необходимости запуска функции возврата в будущем для списка файлов, а затем выполнения действия, которое зависит от их завершения.
Комментарии:
1. В чем проблема с вашим первым примером? Какое значение имеет, выполняется ли функция асинхронно или нет?
2. Я отредактировал вопрос с дополнительной информацией.
Ответ №1:
Когда вам нужно дождаться завершения нескольких фьючерсов, и вас не волнует порядок, вы можете использовать Future.wait():
Future.wait(files.map(functionThatReturnsAFuture))
.then((List response) => print('All files processed'));
Если важен порядок, вы можете вместо этого использовать Future.forEach(), который ожидает завершения каждого Future перед переходом к следующему элементу:
Future.forEach(files, functionThatReturnsAFuture)
.then((response) => print('All files processed'));
Комментарии:
1. ЭТО идеально. Большое вам спасибо! Могу ли я спросить, что бы вы сделали, если бы порядок имел значение?
2. Рад помочь. Я добавил еще немного информации для решения этого случая.
3. И с этим у меня, наконец, достаточно репутации для ответов 1. Вы получаете мой первый 1!
4. Будущее. ожидание занимает итерацию, поэтому нет необходимости сначала составлять список. Просто сделайте
Future.wait(files.map(functionThatReturnsAFuture))
.5. @lrn Ах, спасибо, меня беспокоило, что
Future.wait
код был длиннееFuture.forEach
.
Ответ №2:
Dart поддерживает async
/ await
с довольно долгого времени, что позволяет ему записывать как
someFunc() async {
for(File file in files) {
await functionThatReturnsAFuture(file);
}
}
Комментарии:
1. Я меняю принятый ответ на это, потому что именно так это и должно быть сделано сейчас.
2. Я так старался понять, как это работает. У меня больше внутренних методов. например, внутри функции, которая возвращает метод будущего, другой метод. Так что изначально не сработало. Затем я добавил ту же комбинацию async / await для всех внутренних методов. Затем начал работать, как ожидалось.
3. ожидание перед вызовом метода и асинхронность после подписи метода. Не пропустите это.
Ответ №3:
Эта библиотека может помочь https://pub.dartlang.org/packages/heavylist
HeavyList<File> abc = new HeavyList<File>([new File(), new File(), ]);
abc.loop(new Duration(seconds: 1), (List<File> origin) {
print(origin);
}, (File item, Function resume) {
//simulating an asynchronous call
print(item);
//move to next item
resume();
});