Функция waitFor< T>
- @Deprecated("This functionality is incomplete and may be removed in a later version")
Приостанавливает стек, выполняет микрозадачи и обрабатывает входящие события, пока future не завершится.
Уведомление об устаревании
Функция waitFor устарела. Она предназначалась для решения конкретной проблемы в существующем коде, возникшей из-за несовместимого изменения в библиотеках платформы. Функция waitFor не подходит для общего использования. У неё есть недостатки, которые могут повлиять на другой код, выполняющийся в том же изоляте, в том числе:
- Вызов функции, который выглядит синхронным, может привести к выполнению других асинхронных событий до его возврата. Обычно синхронный код может рассчитывать на то, что этого не произойдёт, и некоторый код мог быть написан с учётом такого поведения. Это может привести к неожиданным сбоям.
- Несколько вложенных вызовов
waitForмогут блокировать друг друга, поскольку последний вызов всегда должен завершиться, прежде чем сможет завершиться любой другой вызов. Чтобы избежать неожиданных взаимоблокировок, которые не возникли бы при использованииawait, необходимо разумно использоватьwaitFor. Если в одной программе несколько библиотек используютwaitFor, трудно избежать или контролировать возникновение такой блокировки.
Эта функция активно не поддерживается. Она останется без изменений, чтобы решать исходную проблему, для которой была добавлена, по крайней мере до тех пор, пока эту проблему нельзя будет решить иным способом.
Семантика вызова
Этот вызов выполняет следующие действия:
- Пока
futureне завершится:- приостанавливает текущий стек выполнения,
- выполняет очередь микрозадач, пока она не опустеет,
- ожидает, пока очередь сообщений не станет непустой,
- обрабатывает сообщения в очереди сообщений и связанные с ними микрозадачи, пока очередь сообщений не опустеет,
- возобновляет исходный стек.
Эта функция нарушает обычную гарантию семантики Dart, согласно которой обработчики сообщений и микрозадачи выполняются до завершения, прежде чем начнёт выполняться следующий обработчик сообщения или микрозадача. Особо следует отметить, что использование этой функции в блоке finally позволяет микрозадачам и обработчикам сообщений выполняться до завершения всех блоков finally для исключения, что может нарушить инварианты вашей программы.
Использование этой функции следует считать крайней мерой, когда невозможно полностью перевести программу на Dart на асинхронный стиль с использованием async и await.
Если Future завершается обычным образом, возвращается его результат. Если Future завершается с ошибкой, ошибка и трассировка стека оборачиваются в AsyncError, который выбрасывается. Если микрозадача или обработчик сообщения, выполняющиеся во время этого вызова, приводят к необработанному исключению, это исключение будет передано так, как если бы микрозадача или обработчик сообщения были единственным вызовом Dart в стеке. Иными словами, необработанные исключения в микрозадаче или обработчике сообщения пропустят стеки, приостановленные во время вызова waitFor.
Если передан необязательный параметр timeout, waitFor выбрасывает TimeoutException, если Future не завершится в течение указанного периода.
Вызовы waitFor могут быть вложенными. Предыдущие вызовы не завершатся, пока не завершатся последующие, но завершение последующего вызова приведёт к пробуждению предыдущего вызова и проверке завершения его Future.
Обратите внимание, что вложенные вызовы waitFor могут привести к взаимоблокировке, если последующие вызовы ожидают условия, которое может быть выполнено только после возврата предыдущего вызова.
Реализация
@Deprecated(
"This functionality is incomplete and may be removed in a later version")
T waitFor<T>(Future<T> future, {Duration? timeout}) {
late T result;
bool futureCompleted = false;
Object? error;
StackTrace? stacktrace;
future.then((T r) {
futureCompleted = true;
result = r;
}, onError: (e, st) {
error = e;
stacktrace = st;
});
late Stopwatch s;
if (timeout != null) {
s = new Stopwatch()..start();
}
Timer.run(() {}); // Ensure there is at least one message.
while (!futureCompleted && (error == null)) {
Duration? remaining;
if (timeout != null) {
if (s.elapsed >= timeout) {
throw new TimeoutException("waitFor() timed out", timeout);
}
remaining = timeout - s.elapsed;
}
_WaitForUtils.waitForEvent(timeout: remaining);
}
if (timeout != null) {
s.stop();
}
Timer.run(() {}); // Ensure that previous calls to waitFor are woken up.
if (error != null) {
throw new AsyncError(error!, stacktrace);
}
return result;
}
© 2012 the Dart project authors
Licensed under the BSD 3-Clause "New" or "Revised" License.
https://api.dart.dev/stable/2.19.6/dart-cli/waitFor.html