Index: sdk/lib/async/future.dart |
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c787f79c1ea3d10fed0bd29304505fa3f397ed67 |
--- /dev/null |
+++ b/sdk/lib/async/future.dart |
@@ -0,0 +1,186 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+// part of dart.async; |
+ |
+/** |
+ * A [Future] is used to obtain a value sometime in the future. Receivers of a |
+ * [Future] can obtain the value by passing a callback to [then]. For example: |
+ * |
+ * Future<int> future = getFutureFromSomewhere(); |
+ * future.then((value) { |
+ * print("I received the number $value"); |
+ * }); |
+ * |
+ * A future may complete by *succeeding* (producing a value) or *failing* |
+ * (producing an error, which may be handled with [catchError]). |
+ * |
+ * When a future completes, the following actions happen in order: |
+ * |
+ * 1. if the future suceeded, handlers registered with [then] are called. |
+ * 2. if the future failed, handlers registered with [catchError] are |
+ * tested in sequence. Each test returning true is, have its handler |
+ * called. |
+ * 4. if the future failed, and no handler registered with [catchError] it |
+ * is accepting the error, an error is sent to the global error handler. |
+ * |
+ * [Future]s are usually not created directly, but with [Completer]s. |
+ */ |
+abstract class Future<T> { |
+ /** A future whose value is immediately available. */ |
+ factory Future.immediate(T value) => new _FutureImpl<T>.immediate(value); |
+ |
+ /** A future that completes with an error. */ |
+ factory Future.immediateError(var error, [Object stackTrace]) { |
+ return new _FutureImpl<T>.immediateError(error, stackTrace); |
+ } |
+ |
+ // TODO(floitsch): I don't think the typing is right here. |
+ // Otherwise new Future<int>.wait(...) would be a Future<List<int>>. Sounds |
+ // wrong. |
+ factory Future.wait(List<Future> futures) |
+ => new _FutureImpl<List<T>>.wait(futures); |
+ |
+ factory Future.delayed(int milliseconds, dynamic value()) { |
+ var completer = new Completer<T>(); |
+ new Timer(milliseconds, (_) => completer.complete(null)); |
+ return completer.future.then((_) => value()); |
+ } |
+ |
+ /** |
+ * When this future completes with a value, then [onValue] is called with this |
+ * value. If [this] future is already completed then the invocation of |
+ * [onValue] is delayed until the next event-loop iteration. |
+ * |
+ * Returns a new [Future] [:f:]. |
+ * |
+ * If [this] is completed with an error then [:f:] is completed with the same |
+ * error. If [this] is completed with a value, then [:f:]'s completion value |
+ * depends on the result of invoking [onValue] with [this]' completion value. |
+ * |
+ * If [onValue] returns a [Future] [:f2:] then [:f:] and [:f2:] are chained. |
+ * That is, [:f:] is completed with the completion value of [:f2:]. |
+ * |
+ * Otherwise [:f:] is completed with the return value of [onValue]. |
+ * |
+ * If [onValue] throws an exception, the returned future will receive the |
+ * exception. |
+ * |
+ * If [onError] is provided, it is called if this future completes with an |
+ * error, and its return value/throw behavior is handled the same way as |
+ * for [onValue]. |
+ * |
+ * 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 |
+ * single [then] call. |
+ */ |
+ Future then(onValue(T value), { onError(AsyncError asyncError) }); |
+ |
+ /** |
+ * If this future is complete with an error, [test] is called with the error. |
+ * If [test] returns [true], [onError] is called with the error |
+ * wrapped in an [AsyncError]. The result of [onError] is handled exactly as |
+ * [then]'s [onValue]. If [test] returns false, the exception is not handled |
+ * by [onError]. If [test] is omitted, it defaults to a function that always |
+ * returns true. |
+ * |
+ * Example: |
+ * foo |
+ * .catchError(..., test: (e) => e is ArgumentError) |
+ * .catchError(..., test: (e) => e is NoSuchMethodError) |
+ * .then((v) { ... }); |
+ */ |
+ Future catchError(onError(AsyncError asyncError), |
+ {bool test(Object error)}); |
+ |
+ /** |
+ * Register a function to be called when this future completes. |
+ * |
+ * The [action] function is called when this future completes, whether it |
+ * does so with a value or with an error. |
+ * |
+ * This is the asynchronous equivalent of a "finally" block. |
+ * |
+ * If the call to [action] does not throw, the returned future is completed |
+ * with the same result as this future. |
+ * |
+ * If the call to [action] throws, the returned future is completed with the |
+ * thrown error. |
+ */ |
+ Future<T> whenComplete(void action()); |
+ |
+ /** |
+ * Creates a [Stream] that sends [this]' completion value, data or error, to |
+ * its subscribers. The stream closes after the completion value. |
+ */ |
+ Stream<T> asStream(); |
+} |
+ |
+/** |
+ * A [Completer] is used to produce [Future]s and supply their value when it |
+ * becomes available. |
+ * |
+ * A service that provides values to callers, and wants to return [Future]s can |
+ * use a [Completer] as follows: |
+ * |
+ * Completer completer = new Completer(); |
+ * // send future object back to client... |
+ * return completer.future; |
+ * ... |
+ * |
+ * // later when value is available, call: |
+ * completer.complete(value); |
+ * |
+ * // alternatively, if the service cannot produce the value, it |
+ * // can provide an exception: |
+ * completer.completeException(exception); |
+ * |
+ */ |
+abstract class Completer<T> { |
+ |
+ factory Completer() => new _CompleterImpl<T>(); |
+ |
+ /** The future that will contain the value produced by this completer. */ |
+ Future get future; |
+ |
+ /** Supply a value for [future]. */ |
+ void complete(T value); |
+ |
+ /** |
+ * Indicate in [future] that an exception occured while trying to produce its |
+ * value. The argument [exception] should not be [:null:]. A [stackTrace] |
+ * object can be provided as well to give the user information about where |
+ * the error occurred. If omitted, it will be [:null:]. |
+ */ |
+ void completeError(Object exception, [Object stackTrace]); |
+} |
+ |
+class Futures { |
+ /** |
+ * Returns a future which will complete once all the futures in a list are |
+ * complete. If any of the futures in the list completes with an exception, |
+ * the resulting future also completes with an exception. (The value of the |
+ * returned future will be a list of all the values that were produced.) |
+ */ |
+ static Future<List> wait(Iterable<Future> futures) { |
+ return new _FutureImpl<List>.wait(futures); |
+ } |
+ |
+ /** |
+ * Runs [f] for each element in [input] in order, moving to the next element |
+ * only when the [Future] returned by [f] completes. Returns a [Future] that |
+ * completes when all elements have been processed. |
+ * |
+ * The return values of all [Future]s are discarded. Any errors will cause the |
+ * iteration to stop and will be piped through the returned [Future]. |
+ */ |
+ static Future forEach(Iterable input, Future f(element)) { |
+ var iterator = input.iterator; |
+ Future nextElement(_) { |
+ if (!iterator.moveNext()) return new Future.immediate(null); |
+ return f(iterator.current).then(nextElement); |
+ } |
+ return nextElement(null); |
+ } |
+} |