Appearance
FutureExtensions<T>
extension FutureExtensions<T> on Future<T>Convenience methods on futures.
Adds functionality to futures which makes it easier to write well-typed asynchronous code.
Methods
ignore() extension
void ignore()Completely ignores this future and its result.
Not all futures are important, not even if they contain errors, for example if a request was made, but the response is no longer needed. Simply ignoring a future can result in uncaught asynchronous errors. This method instead handles (and ignores) any values or errors coming from this future, making it safe to otherwise ignore the future.
Use ignore to signal that the result of the future is no longer important to the program, not even if it's an error. If you merely want to silence the "unawaited futures" lint, use the unawaited function instead. That will ensure that an unexpected error is still reported.
Available on Future<T>, provided by the FutureExtensions<T> extension
Implementation
dart
@Since("2.14")
void ignore() {
var self = this;
if (self is _Future<T>) {
self._ignore();
} else {
self.then<void>(_ignore, onError: _ignore);
}
}onError() extension
Future<T> onError<E extends Object>(
FutureOr<T> Function(E error, StackTrace stackTrace) handleError, {
(bool Function(E error))? test,
})Handles errors on this future.
Catches errors of type E that this future complete with. If test is supplied, only catches errors of type E where test returns true. If E is Object, then all errors are potentially caught, depending only on a supplied test.
If the error is caught, the returned future completes with the result of calling handleError with the error and stack trace. This result must be a value of the same type that this future could otherwise complete with. For example, if this future cannot complete with null, then handleError also cannot return null. Example:
dart
Future<T> retryOperation<T>(Future<T> operation(), T onFailure()) =>
operation().onError<RetryException>((e, s) {
if (e.canRetry) {
return retryOperation(operation, onFailure);
}
return onFailure();
});If handleError throws, the returned future completes with the thrown error and stack trace, except that if it throws the same error object again, then it is considered a "rethrow" and the original stack trace is retained. This can be used as an alternative to skipping the error in test. Example:
dart
// Unwraps an exceptions cause, if it has one.
someFuture.onError<SomeException>((e, _) {
throw e.cause ?? e;
});
// vs.
someFuture.onError<SomeException>((e, _) {
throw e.cause!;
}, test: (e) => e.cause != null);If the error is not caught, the returned future completes with the same result, value or error, as this future.
This method is effectively a more precisely typed version of Future.catchError. It makes it easy to catch specific error types, and requires a correctly typed error handler function, rather than just Function. Because of this, the error handlers must accept the stack trace argument.
Available on Future<T>, provided by the FutureExtensions<T> extension
Implementation
dart
Future<T> onError<E extends Object>(
FutureOr<T> handleError(E error, StackTrace stackTrace), {
bool test(E error)?,
}) {
FutureOr<T> onError(Object error, StackTrace stackTrace) {
if (error is! E || test != null && !test(error)) {
// Counts as rethrow, preserves stack trace.
throw error;
}
return handleError(error, stackTrace);
}
if (this is _Future<Object?>) {
// Internal method working like `catchError`,
// but allows specifying a different result future type.
return unsafeCast<_Future<T>>(this)._safeOnError<T>(onError);
}
return this.then<T>((T value) => value, onError: onError);
}