Future<T> class abstract interface

The result of an asynchronous computation.

An asynchronous computation cannot provide a result immediately when it is started, unlike a synchronous computation which does compute a result immediately by either returning a value or by throwing. An asynchronous computation may need to wait for something external to the program (reading a file, querying a database, fetching a web page) which takes time. Instead of blocking all computation until the result is available, the asynchronous computation immediately returns a Future which will eventually "complete" with the result.

Asynchronous programming

To perform an asynchronous computation, you use an async function which always produces a future. Inside such an asynchronous function, you can use the await operation to delay execution until another asynchronous computation has a result. While execution of the awaiting function is delayed, the program is not blocked, and can continue doing other things.

Example:

import "dart:io";
Future<bool> fileContains(String path, String needle) async {
   var haystack = await File(path).readAsString();
   return haystack.contains(needle);
}

Here the File.readAsString method from dart:io is an asynchronous function returning a Future<String>. The fileContains function is marked with async right before its body, which means that you can use await inside it, and that it must return a future. The call to File(path).readAsString() initiates reading the file into a string and produces a Future<String> which will eventually contain the result. The await then waits for that future to complete with a string (or an error, if reading the file fails). While waiting, the program can do other things. When the future completes with a string, the fileContains function computes a boolean and returns it, which then completes the original future that it returned when first called.

If a future completes with an error, awaiting that future will (re-)throw that error. In the example here, we can add error checking:

import "dart:io";
Future<bool> fileContains(String path, String needle) async {
  try {
    var haystack = await File(path).readAsString();
    return haystack.contains(needle);
  } on FileSystemException catch (exception, stack) {
    _myLog.logError(exception, stack);
    return false;
  }
}

You use a normal try/catch to catch the failures of awaited asynchronous computations.

In general, when writing asynchronous code, you should always await a future when it is produced, and not wait until after another asynchronous delay. That ensures that you are ready to receive any error that the future might produce, which is important because an asynchronous error that no-one is awaiting is an uncaught error and may terminate the running program.

Programming with the Future API.

The Future class also provides a more direct, low-level functionality for accessing the result that it completes with. The async and await language features are built on top of this functionality, and it sometimes makes sense to use it directly. There are things that you cannot do by just awaiting one future at a time.

With a Future, you can manually register callbacks that handle the value, or error, once it is available. For example:

Future<int> future = getFuture();
future.then((value) => handleValue(value))
      .catchError((error) => handleError(error));

Since a Future can be completed in two ways, either with a value (if the asynchronous computation succeeded) or with an error (if the computation failed), you can install callbacks for either or both cases.

In some cases we say that a future is completed with another future. This is a short way of stating that the future is completed in the same way, with the same value or error, as the other future once that other future itself completes. Most functions in the platform libraries that complete a future (for example Completer.complete or Future.value), also accepts another future, and automatically handles forwarding the result to the future being completed.

The result of registering callbacks is itself a Future, which in turn is completed with the result of invoking the corresponding callback with the original future's result. The new future is completed with an error if the invoked callback throws. For example:

Future<int> successor = future.then((int value) {
    // Invoked when the future is completed with a value.
    return 42;  // The successor is completed with the value 42.
  },
  onError: (e) {
    // Invoked when the future is completed with an error.
    if (canHandle(e)) {
      return 499;  // The successor is completed with the value 499.
    } else {
      throw e;  // The successor is completed with the error e.
    }
  });

If a future does not have any registered handler when it completes with an error, it forwards the error to an "uncaught-error handler". This behavior ensures that no error is silently dropped. However, it also means that error handlers should be installed early, so that they are present as soon as a future is completed with an error. The following example demonstrates this potential bug:

var future = getFuture();
Timer(const Duration(milliseconds: 5), () {
  // The error-handler is not attached until 5 ms after the future has
  // been received. If the future fails before that, the error is
  // forwarded to the global error-handler, even though there is code
  // (just below) to eventually handle the error.
  future.then((value) { useValue(value); },
              onError: (e) { handleError(e); });
});

When registering callbacks, it's often more readable to register the two callbacks separately, by first using then with one argument (the value handler) and using a second catchError for handling errors. Each of these will forward the result that they don't handle to their successors, and together they handle both value and error result. It has the additional benefit of the catchError handling errors in the then value callback too. Using sequential handlers instead of parallel ones often leads to code that is easier to reason about. It also makes asynchronous code very similar to synchronous code:

// Synchronous code.
try {
  int value = foo();
  return bar(value);
} catch (e) {
  return 499;
}

Equivalent asynchronous code, based on futures:

Future<int> asyncValue = Future(foo);  // Result of foo() as a future.
asyncValue.then((int value) {
  return bar(value);
}).catchError((e) {
  return 499;
});

Similar to the synchronous code, the error handler (registered with catchError) is handling any errors thrown by either foo or bar. If the error-handler had been registered as the onError parameter of the then call, it would not catch errors from the bar call.

Futures can have more than one callback-pair registered. Each successor is treated independently and is handled as if it was the only successor. The order in which the individual successors are completed is undefined.

A future may also fail to ever complete. In that case, no callbacks are called. That situation should generally be avoided if possible, unless it's very clearly documented.

Available extensions
Annotations
  • @vmIsolateUnsendable

Constructors

Future.new(FutureOr<T> computation())
Creates a future containing the result of calling computation asynchronously with Timer.run.
factory
Future.delayed(Duration duration, [FutureOr<T> computation()?])
Creates a future that runs its computation after a delay.
factory
Future.error(Object error, [StackTrace? stackTrace])
Creates a future that completes with an error.
factory
Future.microtask(FutureOr<T> computation())
Creates a future containing the result of calling computation asynchronously with scheduleMicrotask.
factory
Future.sync(FutureOr<T> computation())
Returns a future containing the result of immediately calling computation.
factory
Future.value([FutureOr<T>? value])
Creates a future completed with value.
factory

Properties

asListAsync Future<List<T>>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
asListOrNullAsync Future<List<T>?>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

no setter
firstAsync Future<T>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
firstOrNullAsync Future<T?>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
firstOrNullAsync Future<T?>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

no setter
genericType Type

Available on Future<T>, provided by the FutureExtension extension

Returns the type of T.
no setter
hashCode int
The hash code for this object.
no setterinherited
isEmptyAsync Future<bool>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
isEmptyOrNullAsync Future<bool>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

no setter
isNotEmptyAsync Future<bool>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
isNotEmptyAsync Future<bool>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

no setter
lastAsync Future<T>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
lastOrNullAsync Future<T?>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
lastOrNullAsync Future<T?>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

no setter
lengthAsync Future<int>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

no setter
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
toJS JSPromise<T>

Available on Future<T>, provided by the FutureOfJSAnyToJSPromise extension

A JSPromise that either resolves with the result of the completed Future or rejects with an object that contains its error.
no setter
toJS JSPromise<JSAny?>

Available on Future<void>, provided by the FutureOfVoidToJSPromise extension

A JSPromise that either resolves once this Future completes or rejects with an object that contains its error.
no setter

Methods

asStream() Stream<T>
Creates a Stream containing the result of this future.
catchError(Function onError, {bool test(Object error)?}) Future<T>
Handles errors emitted by this Future.
ignore() → void

Available on Future<T>, provided by the FutureExtensions extension

Completely ignores this future and its result.
logError({AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T>

Available on Future<T>, provided by the FutureOnErrorExtension extension

Logs a Future error using errorLogger or defaultAsyncExtensionErrorLogger if parameter logError is true.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
nullOnError({FutureOr<void> onError(Object e, StackTrace s)?, AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T?>

Available on Future<T>, provided by the FutureNonNullOnErrorExtension extension

Returns this Future value or null if it throws an error.
nullOnError({FutureOr<void> onError(Object e, StackTrace s)?, FutureOr<void> onErrorOrNull(Object? e, StackTrace? s)?, AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T?>

Available on Future<T?>, provided by the FutureNullableOnErrorExtension extension

Returns this Future value or null if it throws an error.
onComplete({required FutureOr<void> onSuccess(T r), required FutureOr<void> onError(Object e, StackTrace s), AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T?>

Available on Future<T>, provided by the FutureNonNullOnErrorExtension extension

Calls onSuccess or onError when this Future completes.
onComplete({required FutureOr<void> onSuccess(T? r), FutureOr<void> onError(Object e, StackTrace s)?, FutureOr<void> onErrorOrNull(Object? e, StackTrace? s)?, AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T?>

Available on Future<T?>, provided by the FutureNullableOnErrorExtension extension

Calls onSuccess or onError when this Future completes. If onErrorOrNull is defined, calls onErrorOrNull if it completes with null or with an error.
onCompleteNotNull({required FutureOr<void> onSuccess(T r), required FutureOr<void> onErrorOrNull(Object? e, StackTrace? s), AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T?>

Available on Future<T?>, provided by the FutureNullableOnErrorExtension extension

Calls onSuccess or onErrorOrNull when this Future completes. Calls onErrorOrNull If it completes with null or with an error.
onError<E extends Object>(FutureOr<T> handleError(E error, StackTrace stackTrace), {bool test(E error)?}) Future<T>

Available on Future<T>, provided by the FutureExtensions extension

Handles errors on this future.
onErrorReturn(T onErrorValue, {FutureOr<void> onError(Object e, StackTrace s)?, AsyncExtensionErrorLogger? errorLogger, bool logError = true}) Future<T>

Available on Future<T>, provided by the FutureOnErrorExtension extension

Returns this Future value or onErrorValue if it throws an error.
orElseAsync(T defaultValue) Future<T>

Available on Future<T?>, provided by the FutureNullableExtension extension

Returns the value of this Future (T). If the value is null, it will return the defaultValue.
orElseGeAsync(FutureOr<T> defaultGetter()) Future<T>

Available on Future<T?>, provided by the FutureNullableExtension extension

Returns the value of this Future (T). If the value is null, it will return the value returned by defaultGetter.
resolveBoth<R>(FutureOr<T> other, FutureOr<R> resolver(T val1, T val2)) Future<R>

Available on Future<T>, provided by the FutureExtension extension

Resolves this Future and other with resolver.
then<R>(FutureOr<R> onValue(T value), {Function? onError}) Future<R>
Register callbacks to be called when this future completes.
timeout(Duration timeLimit, {FutureOr<T> onTimeout()?}) Future<T>
Stop waiting for this future after timeLimit has passed.
toListAsync({bool growable = true}) FutureOr<List<T>>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

toListOrNullAsync({bool growable = true}) Future<List<T>?>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

toSetAsync() Future<Set<T>>

Available on Future<Iterable<T>>, provided by the FutureIterableExtension extension

toSetOrNullAsync() Future<Set<T>?>

Available on Future<Iterable<T>?>, provided by the FutureIterableNullableExtension extension

toString() String
A string representation of this object.
inherited
whenComplete(FutureOr<void> action()) Future<T>
Registers a function to be called when this future completes.

Operators

operator *(FutureOr<double> other) Future<double>

Available on Future<double>, provided by the FutureDoubleExtension extension

Operator to multiply FutureOr<double>.
operator *(FutureOr<int> other) Future<int>

Available on Future<int>, provided by the FutureIntExtension extension

Operator to multiply FutureOr<int>.
operator *(FutureOr<num> other) Future<num>

Available on Future<num>, provided by the FutureNumExtension extension

Operator to multiply FutureOr<num>.
operator +(FutureOr<double> other) Future<double>

Available on Future<double>, provided by the FutureDoubleExtension extension

Operator to sum FutureOr<double>.
operator +(FutureOr<int> other) Future<int>

Available on Future<int>, provided by the FutureIntExtension extension

Operator to sum FutureOr<int>.
operator +(FutureOr<num> other) Future<num>

Available on Future<num>, provided by the FutureNumExtension extension

Operator to sum FutureOr<num>.
operator -(FutureOr<double> other) Future<double>

Available on Future<double>, provided by the FutureDoubleExtension extension

Operator to subtract FutureOr<double>.
operator -(FutureOr<int> other) Future<int>

Available on Future<int>, provided by the FutureIntExtension extension

Operator to subtract FutureOr<int>.
operator -(FutureOr<num> other) Future<num>

Available on Future<num>, provided by the FutureNumExtension extension

Operator to subtract FutureOr<num>.
operator /(FutureOr<double> other) Future<double>

Available on Future<double>, provided by the FutureDoubleExtension extension

Operator to divide FutureOr<double>.
operator /(FutureOr<int> other) Future<double>

Available on Future<int>, provided by the FutureIntExtension extension

Operator to divide FutureOr<int>.
operator /(FutureOr<num> other) Future<double>

Available on Future<num>, provided by the FutureNumExtension extension

Operator to divide FutureOr<num>.
operator ==(Object other) bool
The equality operator.
inherited
operator ~/(FutureOr<double> other) Future<int>

Available on Future<double>, provided by the FutureDoubleExtension extension

Operator to divide (to int) FutureOr<int>.
operator ~/(FutureOr<int> other) Future<int>

Available on Future<int>, provided by the FutureIntExtension extension

Operator to divide (to int) FutureOr<int>.
operator ~/(FutureOr<num> other) Future<int>

Available on Future<num>, provided by the FutureNumExtension extension

Operator to divide (to int) FutureOr<num>.

Static Methods

any<T>(Iterable<Future<T>> futures) Future<T>
Returns the result of the first future in futures to complete.
doWhile(FutureOr<bool> action()) Future<void>
Performs an operation repeatedly until it returns false.
forEach<T>(Iterable<T> elements, FutureOr action(T element)) Future<void>
Performs an action for each element of the iterable, in turn.
wait<T>(Iterable<Future<T>> futures, {bool eagerError = false, void cleanUp(T successValue)?}) Future<List<T>>
Waits for multiple futures to complete and collects their results.