Будущее /async/ожидание в Dart
У меня есть функция loadData
которая загружает некоторый текст из файла:
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/data/entities.json');
}
Метод loadString
- от Flutter SDK и является асинхронным.
Затем метод loadAsset
вызывается другим методом, который должен быть помечен как async
, поскольку loadAsset
является асинхронным, и мне нужно использовать await
:
Future<List<Entity>> loadEntities() async {
String jsonData = await loadAsset();
return parseData(jsonData);
}
Метод parseData
не является асинхронным, он получает String
, анализирует ее и возвращает список объектов:
List<Entity> parseData(String jsonString) {
...
}
Но поскольку loadEntities
должен быть помечен async
, для этого требуется, чтобы он возвращал Future
, но на практике это не Future
потому что, поскольку я использую await
, он ждет loadAsset
метода loadAsset
, а затем вызовет parseData
с использованием результата.
Это легко превращается в снежный ком async
вызова, потому что каждый метод, который использует loadEntities
должен быть помечен как async
.
Кроме того, я не могу использовать loadEntities
в конструкторе класса, потому что конструктор должен быть помечен как async
, что запрещено в Dart.
Я использую шаблон async/await
в Dart неправильно? Как я могу использовать метод loadEntities
в конструкторе класса?
Ответы
Ответ 1
Нет, async заразителен, и нет возможности вернуться от асинхронного к синхронизации.
async
/await
- это только синтаксический сахар для methodThatReturnsFuture().then(...)
Маркировка метода с помощью async
- это только позволить вам использовать await
внутри своего тела. Без async
вам все равно нужно вернуть Future
для вызова кода только после того, как будет loadAsset()
результат loadAsset()
.
Ответ 2
Вы можете использовать Будущее, возвращенное из асинхронного вызова напрямую. Это будет выглядеть примерно так:
class HasAsync {
HasAsync() {
asyncFunction().then((val) {
print(val);
});
}
Future<int> asyncFunction() async {
int val = await otherFunction();
return val;
}
}
Вы просто не можете использовать ожидание внутри функции non-async.
Поскольку вы отметили это с помощью флаттера, я собираюсь угадать, что это приложение для флаттера. Если этот случай рассмотрит документы для FutureBuilder - это может помочь в том, что вы пытаетесь сделать.
Ответ 3
Просто исправление:
асинхронные методы НЕ заразны.
Конструктор Test вызывает асинхронный метод sayHello.
Это демонстрирует, как заставить ctor сделать асинхронный вызов, когда его нельзя объявить асинхронным.
Основной метод помечается как асинхронный просто, чтобы приложение не закрывалось до завершения sayHello. Это не внутреннее требование.
class Test
{
Test()
{
sayHello();
}
void sayHello() async
{
await Future.delayed(Duration(seconds: 4) , () => print("Hello"));
print("We said hello");
}
}
void main() async
{
doTest();
// wait for hello to be output
await Future.delayed(Duration(seconds: 6) , () {});
print("Ending");
}
void doTest()
{
Test();
}
Ответ 4
У меня есть статья, объясняющая это https://medium.com/@truongsinh/flutter-dart-async-concurrency-demystify-1cc739aaae57
Короче говоря, Flutter/Dart не является технически однопоточным, хотя код Dart выполняется в одном потоке. Dart - это параллельный язык с шаблоном передачи сообщений, который может в полной мере использовать преимущества современной многоядерной архитектуры, не беспокоясь о блокировке или мьютексе. Блокировка в Dart может быть привязана либо к I/O, либо к CPU, что должно быть решено, соответственно, вычислениями Future и Darts Isolate/Flutters.