Библиотеки Dart полны функций, которые возвращают объекты Future
или Stream
. Эти функции являются асинхронными: они возвращаются после настройки, возможно, трудоемкой операции (например, ввода-вывода), не дожидаясь завершения этой операции.
Ключевые слова async
и await
поддерживают асинхронное программирование, позволяя вам писать асинхронный код, который похож на синхронный код.
Обработка Future
Когда вам нужен результат завершенного будущего, у вас есть два варианта:
- Используй
async
иawait
. - Используйте Future API, как описано в обзоре библиотеки.
Код, который использует async
и await
, является асинхронным, но очень похож на синхронный код. Например, вот код, который использует await
для ожидания результата асинхронной функции:
await lookUpVersion();
Чтобы использовать await
, код должен быть в функции async
— функции, помеченной как async
:
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
Используйте try
, catch
и finally
для обработки ошибок и очистки в коде, который использует await:
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
Вы можете использовать await
несколько раз в функции async
. Например, следующий код трижды ожидает результатов функций:
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
В await
expression
, значение expression
обычно является будущим; если это не так, то значение автоматически переносится в будущее. Этот объект Future указывает на обещание вернуть объект. Значением await epression
является возвращаемый объект. Выражение await
останавливает выполнение до тех пор, пока этот объект не станет доступен.
Если вы получаете ошибку времени компиляции при использовании await
, убедитесь, что await
находится в функции async
. Например, чтобы использовать await
в функции main()
вашего приложения, тело main()
должно быть помечено как async
:
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
Объявление асинхронных функций
Функция async
— это функция, тело которой помечено модификатором асинхронности async.
Добавление ключевого слова async
в функцию возвращает Future. Например, рассмотрим эту синхронную функцию, которая возвращает строку:
String lookUpVersion() => '1.0.0';
Если вы измените его на асинхронную функцию через async
— например, потому что будущая реализация будет занимать много времени — возвращаемое значение будет Future:
Future<string> lookUpVersion() async => '1.0.0';
Обратите внимание, что телу функции не нужно использовать Future API. Dart создает объект Future, если это необходимо. Если ваша функция не возвращает полезное значение, сделайте возвращаемый тип Future<void>
.
Интерактивное введение в использование futures
, async
и await
см. В разделе кодовой метки асинхронного программирования.
Обработка потоков
Когда вам нужно получить значения из потока, у вас есть два варианта:
- Используйте
async
и асинхронный цикл for (await for
). - Используйте Stream API, как описано в обзоре библиотеки.
await for
убедитесь, что это делает код более понятным и что вы действительно хотите дождаться всех результатов потока. Например, вам обычно не следует использовать await for
для слушателей событий пользовательского интерфейса, поскольку платформы пользовательского интерфейса отправляют бесконечные потоки событий. Асинхронный цикл for имеет следующую форму:
await for (varOrType identifier in expression) {
// Executes each time the stream emits a value.
}
Значение выражения expression
должно иметь тип Stream
. Исполнение происходит следующим образом:
- Подождите, пока поток не выдаст значение.
- Выполнить тело цикла for с переменной, установленной на это значение.
- Повторите 1 и 2, пока поток не будет закрыт.
Чтобы прекратить прослушивание потока, вы можете использовать оператор break
или return
, который выходит из цикла for и отписывается от потока.
Если вы получили ошибку во время компиляции при реализации асинхронного цикла for
, убедитесь, что await for
находится в асинхронной функции async
. Например, чтобы использовать асинхронный цикл for
в функции main()
вашего приложения, тело main()
должно быть помечено как async
:
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
Для получения дополнительной информации об асинхронном программировании, в общем, смотрите раздел dart:async в обзоре библиотеки.