Future<T> class Null safety
An object representing a delayed computation.
A Future is used to represent a potential value, or error, that will be available at some time in the future. Receivers of a Future can 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));
A Future can be completed in two ways: with a value ("the future succeeds") or with an error ("the future fails"). Users can install callbacks for each case.
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 completes. Whenever a function in the core library may complete a future (for example Completer.complete or new Future.value), then it also accepts another future and does this work for the developer.
The result of registering a pair of callbacks is a new Future (the "successor") which in turn is completed with the result of invoking the corresponding callback. The successor 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 a successor when it completes with an error, it forwards the error message to the global error-handler. This behavior makes sure 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();
new Timer(new 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 also 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> future = new Future(foo); // Result of foo() as a future.
future.then((int value) => bar(value))
.catchError((e) => 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.
A future may also fail to ever complete. In that case, no callbacks are called.
Constructors
-
Future(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
- hashCode → int
-
The hash code for this object. [...]
read-only, inherited
- runtimeType → Type
-
A representation of the runtime type of the object.
read-only, inherited
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. [...]
-
noSuchMethod(
Invocation invocation ) → dynamic -
Invoked when a non-existent method or property is accessed. [...]
inherited
-
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> -
Time-out the future computation after
timeLimit
has passed. [...] -
toString(
) → String -
Returns 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 ==(
Object other ) → bool -
The equality operator. [...]
inherited
Static Methods
-
any<
T> (Iterable< Future< futuresT> >) → Future< T> -
Returns the result of the first future in
futures
to complete. [...] -
doWhile(
FutureOr< bool> action()) → Future -
Performs an operation repeatedly until it returns
false
. [...] -
forEach<
T> (Iterable< T> elements,FutureOr action(T element ) ) → Future - Performs an action for each element of the iterable, in turn. [...]
-
wait<
T> (Iterable< Future< futures,T> >{bool eagerError: false, void cleanUp(T successValue )} ) → Future< List< T> > - Waits for multiple futures to complete and collects their results. [...]