wait метод
Future<List<T>> wait<T>(Ожидание завершения всех заданных будущих задач и сбор их значений.
Возвращает будущую задачу, которая завершится, когда все будущие задачи в списке завершатся.
Значение возвращаемой будущей задачи будет списком всех значений, которые были получены.
Если какая-либо из заданных будущих задач завершится с ошибкой, то возвращаемая будущая задача завершится с этой ошибкой. Если другие будущие задачи завершатся с ошибками, эти ошибки будут проигнорированы.
Если eagerError равно true, возвращаемая будущая задача завершится с ошибкой сразу после первой ошибки от одной из будущих задач. В противном случае все будущие задачи должны завершиться, прежде чем возвращаемая будущая задача завершится (все равно с первой ошибкой; оставшиеся ошибки будут проигнорированы).
В случае ошибки cleanUp (если предоставлена), вызывается для любого непустого результата успешных будущих задач. Это позволяет cleanUp ресурсы, которые в противном случае были бы потеряны (поскольку возвращаемая будущая задача не предоставляет доступ к этим значениям). Функция cleanup не используется, если ошибки нет.
Вызов cleanUp не должен вызывать исключения. Если это произойдет, ошибка станет необработанной асинхронной ошибкой.
Источник
static Future<List<T>> wait<T>(Iterable<Future<T>> futures,
{bool eagerError: false, void cleanUp(T successValue)}) {
final _Future<List<T>> result = new _Future<List<T>>();
List<T> values; // Collects the values. Set to null on error.
int remaining = 0; // How many futures are we waiting for.
var error; // The first error from a future.
StackTrace stackTrace; // The stackTrace that came with the error.
// Handle an error from any of the futures.
// TODO(jmesserly): use `void` return type once it can be inferred for the
// `then` call below.
handleError(theError, theStackTrace) {
remaining--;
if (values != null) {
if (cleanUp != null) {
for (var value in values) {
if (value != null) {
// Ensure errors from cleanUp are uncaught.
new Future.sync(() {
cleanUp(value);
});
}
}
}
values = null;
if (remaining == 0 || eagerError) {
result._completeError(theError, theStackTrace);
} else {
error = theError;
stackTrace = theStackTrace;
}
} else if (remaining == 0 && !eagerError) {
result._completeError(error, stackTrace);
}
}
try {
// As each future completes, put its value into the corresponding
// position in the list of values.
for (Future future in futures) {
int pos = remaining;
future.then((T value) {
remaining--;
if (values != null) {
values[pos] = value;
if (remaining == 0) {
result._completeWithValue(values);
}
} else {
if (cleanUp != null && value != null) {
// Ensure errors from cleanUp are uncaught.
new Future.sync(() {
cleanUp(value);
});
}
if (remaining == 0 && !eagerError) {
result._completeError(error, stackTrace);
}
}
}, onError: handleError);
// Increment the 'remaining' after the call to 'then'.
// If that call throws, we don't expect any future callback from
// the future, and we also don't increment remaining.
remaining++;
}
if (remaining == 0) {
return new Future.value(const []);
}
values = new List<T>(remaining);
} catch (e, st) {
// The error must have been thrown while iterating over the futures
// list, or while installing a callback handler on the future.
if (remaining == 0 || eagerError) {
// Throw a new Future.error.
// Don't just call `result._completeError` since that would propagate
// the error too eagerly, not giving the callers time to install
// error handlers.
// Also, don't use `_asyncCompleteError` since that one doesn't give
// zones the chance to intercept the error.
return new Future.error(e, st);
} else {
// Don't allocate a list for values, thus indicating that there was an
// error.
// Set error to the caught exception.
error = e;
stackTrace = st;
}
}
return result;
}
© 2012 the Dart project authors
Licensed under the Creative Commons Attribution-ShareAlike License v4.0.
https://api.dartlang.org/stable/1.24.3/dart-async/Future/wait.html