| Index: sdk/lib/async/future.dart
|
| diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
|
| index b7ad177dececd13c467974e832d39a8eeae0946a..5e0206922b8d73da6ec7abc603107678416010d7 100644
|
| --- a/sdk/lib/async/future.dart
|
| +++ b/sdk/lib/async/future.dart
|
| @@ -7,21 +7,25 @@ part of dart.async;
|
| /**
|
| * An object representing a delayed computation.
|
| *
|
| - * A [Future] is used to obtain a not yet
|
| - * available value, or error, sometime in the future. Receivers of a
|
| - * [Future] can register callbacks that handle the value or error once it is
|
| - * available. For example:
|
| + * 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. The result of registering a pair of callbacks is a new Future (the
|
| + * A [Future] can complete in two ways:
|
| + * with a value ("the future succeeds")
|
| + * or with an error ("the future fails").
|
| + * Users can install callbacks for each case.
|
| + * 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:
|
| + * 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.
|
| @@ -36,31 +40,33 @@ part of dart.async;
|
| * }
|
| * });
|
| *
|
| - * If a future does not have a successor but is completed with an error, it
|
| - * forwards the error message to the global error-handler. This special casing
|
| - * 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:
|
| + * 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 only attached 5ms after the future has been
|
| - * // received. If the future fails in the mean-time it will forward the
|
| - * // error to the global error-handler, even though there is code (just
|
| - * // below) to handle the error.
|
| + * // 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); });
|
| * });
|
| *
|
| - * In general we discourage registering the two callbacks at the same time, but
|
| - * prefer to use [then] with one argument (the value handler), and to use
|
| - * [catchError] for handling errors. The missing callbacks (the error-handler
|
| - * for [then], and the value-handler for [catchError]), are automatically
|
| - * configured to "forward" the value/error. Separating value and error-handling
|
| - * into separate registration calls usually leads to code that is easier to
|
| - * reason about. In fact it makes asynchronous code very similar to synchronous
|
| - * code:
|
| + * 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 {
|
| @@ -70,21 +76,23 @@ part of dart.async;
|
| * return 499;
|
| * }
|
| *
|
| - * Equivalent asynchronous code, based on futures:
|
| + * Equivalent asynchronous code, based on futures:
|
| *
|
| - * Future<int> future = foo(); // foo now returns a future.
|
| + * 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 the errors for exceptions coming from calls to
|
| - * 'foo', as well as 'bar'. This would not be the case if the error-handler was
|
| - * registered at the same time as the value-handler.
|
| + * [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-pairs registered. Each successor is
|
| + * 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.
|
| */
|
| -// TODO(floitsch): document chaining.
|
| abstract class Future<T> {
|
| // The `_nullFuture` is a completed Future with the value `null`.
|
| static final _Future _nullFuture = new Future.value(null);
|
| @@ -100,7 +108,8 @@ abstract class Future<T> {
|
| * the created future will wait until the returned future completes,
|
| * and will then complete with the same result.
|
| *
|
| - * If a value is returned, it becomes the result of the created future.
|
| + * If a non-future value is returned, the returned future is completed
|
| + * with that value.
|
| */
|
| factory Future(computation()) {
|
| _Future result = new _Future<T>();
|
| @@ -118,14 +127,15 @@ abstract class Future<T> {
|
| * Creates a future containing the result of calling [computation]
|
| * asynchronously with [scheduleMicrotask].
|
| *
|
| - * If the result of executing [computation] throws, the returned future is
|
| - * completed with the error.
|
| + * If executing [computation] throws,
|
| + * the returned future is completed with the thrown error.
|
| *
|
| - * If the returned value is itself a [Future], completion of
|
| + * If calling [computation] returns a [Future], completion of
|
| * the created future will wait until the returned future completes,
|
| * and will then complete with the same result.
|
| *
|
| - * If a value is returned, it becomes the result of the created future.
|
| + * If calling [computation] returns a non-future value,
|
| + * the returned future is completed with that value.
|
| */
|
| factory Future.microtask(computation()) {
|
| _Future result = new _Future<T>();
|
| @@ -146,9 +156,12 @@ abstract class Future<T> {
|
| * If calling [computation] throws, the returned future is completed with the
|
| * error.
|
| *
|
| - * If the returned value is itself a [Future], completion of
|
| + * If calling [computation] returns a [Future], completion of
|
| * the created future will wait until the returned future completes,
|
| * and will then complete with the same result.
|
| + *
|
| + * If calling [computation] returns a non-future value,
|
| + * the returned future is completed with that value.
|
| */
|
| factory Future.sync(computation()) {
|
| try {
|
| @@ -165,7 +178,7 @@ abstract class Future<T> {
|
| * If [value] is not a [Future], using this constructor is equivalent
|
| * to [:new Future<T>.sync(() => value):].
|
| *
|
| - * See [Completer] to create a Future and complete it later.
|
| + * Use [Completer] to create a Future and complete it later.
|
| */
|
| factory Future.value([value]) {
|
| return new _Future<T>.immediate(value);
|
| @@ -174,7 +187,7 @@ abstract class Future<T> {
|
| /**
|
| * A future that completes with an error in the next event-loop iteration.
|
| *
|
| - * See [Completer] to create a Future and complete it later.
|
| + * Use [Completer] to create a Future and complete it later.
|
| */
|
| factory Future.error(Object error, [StackTrace stackTrace]) {
|
| return new _Future<T>.immediateError(error, stackTrace);
|
| @@ -187,14 +200,15 @@ abstract class Future<T> {
|
| * the result of calling [computation]. If the duration is 0 or less, it
|
| * completes no sooner than in the next event-loop iteration.
|
| *
|
| - * If [computation] is not given or [:null:] then it will behave as if
|
| - * [computation] was set to [:() => null:]. That is, it will complete with
|
| - * [:null:].
|
| + * If [computation] is omitted,
|
| + * it will be treated as if [computation] was set to `() => null`,
|
| + * and the future will eventually complete with the `null` value.
|
| *
|
| * If calling [computation] throws, the created future will complete with the
|
| * error.
|
| *
|
| - * See [Completer]s, for futures with values that are computed asynchronously.
|
| + * See also [Completer] for a way to complete a future at a later
|
| + * time that isn't a known fixed duration.
|
| */
|
| factory Future.delayed(Duration duration, [T computation()]) {
|
| Completer completer = new Completer.sync();
|
| @@ -316,7 +330,7 @@ abstract class Future<T> {
|
| * the returned future is completed with the thrown error
|
| * and a stack trace for the error.
|
| * In the case of `onError`,
|
| - * if the exception thrown is the same as the argument to `onError`,
|
| + * if the exception thrown is `identical` to the error argument to `onError`,
|
| * the throw is considered a rethrow,
|
| * and the original stack trace is used instead.
|
| *
|
| @@ -324,7 +338,8 @@ abstract class Future<T> {
|
| * the future returned by `then` will be completed with
|
| * the same result of the future returned by the callback.
|
| *
|
| - * If [onError] is not given it forwards the error to `f`.
|
| + * If [onError] is not given, and this future completes with an error,
|
| + * the error is forwarded directly to the returned future.
|
| *
|
| * In most cases, it is more readable to use [catchError] separately, possibly
|
| * with a `test` parameter, instead of handling both value and error in a
|
|
|