race<T> static method
- Iterable<
CancelableOperation< operationsT> >
Creates a CancelableOperation that completes with the value of the first
of operations
to complete.
Once any of operations
completes, its result is forwarded to the
new CancelableOperation and the rest are cancelled. If the
bew operation is cancelled, all the operations
are cancelled as
well.
Implementation
static CancelableOperation<T> race<T>(
Iterable<CancelableOperation<T>> operations) {
operations = operations.toList();
if (operations.isEmpty) {
throw ArgumentError('May not be empty', 'operations');
}
var done = false;
// Note: if one or more of the completers have already completed,
// they're not actually cancelled by this.
Future<void> cancelAll() {
done = true;
return Future.wait(operations.map((operation) => operation.cancel()));
}
var completer = CancelableCompleter<T>(onCancel: cancelAll);
for (var operation in operations) {
operation.then((value) {
if (!done) cancelAll().whenComplete(() => completer.complete(value));
}, onError: (error, stackTrace) {
if (!done) {
cancelAll()
.whenComplete(() => completer.completeError(error, stackTrace));
}
});
}
return completer.operation;
}