Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.async; | 5 part of dart.async; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A [Future] is used to obtain a value sometime in the future. Receivers of a | 8 * A [Future] represents a delayed computation. It is used to obtain a not-yet |
| 9 * [Future] can obtain the value by passing a callback to [then]. For example: | 9 * available value, or error, sometime in the future. Receivers of a |
| 10 * [Future] can register callbacks that handle the value or error once it is | |
| 11 * available. For example: | |
| 10 * | 12 * |
| 11 * Future<int> future = getFutureFromSomewhere(); | 13 * Future<int> future = getFuture(); |
| 12 * future.then((value) { | 14 * future.then((value) { |
| 13 * print("I received the number $value"); | 15 * print("I received the number $value"); |
| 14 * }); | 16 * }); |
| 15 * | 17 * |
| 16 * A future may complete by *succeeding* (producing a value) or *failing* | 18 * A [Future] can be completed in two ways: with a value ("the future succeeds") |
| 17 * (producing an error, which may be handled with [catchError]). | 19 * or with an error ("the future fails"). Users can install callbacks for each |
| 20 * case. The result of registering a pair of callbacks is a new Future (the | |
| 21 * "successor") which in turn is completed with the result of invoking the | |
| 22 * corresponding callback. The successor is completed with an error if the | |
| 23 * invoked callback throws. For example: | |
| 18 * | 24 * |
| 19 * When a future completes, the following actions happen in order: | 25 * Future<int> successor = future.then((int value) { |
|
nweiz
2013/01/11 19:55:06
Nit: indent this line +2 spaces
floitsch
2013/01/11 20:46:09
Done.
| |
| 26 * // Invoked when the future is completed with a value. | |
| 27 * return 42; // The successor is completed with the value 42. | |
| 28 * }, | |
| 29 * onError: (AsyncError e) { | |
| 30 * // Invoked when the future is completed with an error. | |
| 31 * if (canHandle(e)) { | |
| 32 * return 499; // The successor is completed with the value 499. | |
| 33 * } else { | |
| 34 * throw e; // The successor is completed with the error e. | |
| 35 * } | |
| 36 * }); | |
|
nweiz
2013/01/11 19:55:06
It would be nice to make the first error-handling
floitsch
2013/01/11 20:46:09
Added a catchError in the first example.
nweiz
2013/01/11 21:39:06
As I mentioned offline, I think it's important to
| |
| 20 * | 37 * |
| 21 * 1. if the future suceeded, handlers registered with [then] are called. | 38 * If a future does not have a successor but is completed with an error, it |
| 22 * 2. if the future failed, handlers registered with [catchError] are | 39 * forwards the error message to the global error-handler. This special casing |
| 23 * tested in sequence. Each test returning true is, have its handler | 40 * makes sure that no error is silently dropped. However, it also means that |
| 24 * called. | 41 * error handlers should be installed early, so that they are present as soon |
| 25 * 4. if the future failed, and no handler registered with [catchError] it | 42 * as a future is completed with an error. The following example demonstrates |
| 26 * is accepting the error, an error is sent to the global error handler. | 43 * this potential bug: |
| 27 * | 44 * |
| 28 * [Future]s are usually not created directly, but with [Completer]s. | 45 * var future = getFuture(); |
|
nweiz
2013/01/11 19:55:06
Nit: I think this whole block (and the ones below)
floitsch
2013/01/11 20:46:09
Done.
| |
| 46 * new Timer(5, (_) { | |
| 47 * // The error-handler is only attached 5ms after the future has been | |
| 48 * // received. If the future fails in the mean-time it will forward the | |
| 49 * // error to the global error-handler, even though there is code (just | |
| 50 * // below) to handle the error. | |
| 51 * future.then((value) { useValue(value); }, | |
| 52 * onError: (e) { handleError(e); }); | |
| 53 * }); | |
| 54 * | |
| 55 * In general we discourage registering the two callbacks at the same time, but | |
| 56 * prefer to use [then] with one argument (the value handler), and to use | |
| 57 * [catchError] for handling errors. The missing callbacks (the error-handler | |
| 58 * for [then], and the value-handler for [catchError]), are automatically | |
| 59 * configured to "forward" the value/error. Separating value and error-handling | |
| 60 * into separate registration calls usually leads to code that is easier to | |
| 61 * reason about. In fact it makes asynchronous code very similar to synchronous | |
| 62 * code: | |
| 63 * | |
| 64 * // Synchronous code. | |
| 65 * try { | |
| 66 * int value = foo(); | |
| 67 * return bar(value); | |
| 68 * } catch (e) { | |
| 69 * return 499; | |
| 70 * } | |
| 71 * | |
| 72 * Equivalent asynchronous code, based on futures: | |
| 73 * | |
| 74 * Future<int> future = foo(); // foo now returns a future. | |
| 75 * future.then((int value) => bar(value)) | |
| 76 * .catchError((e) => 499); | |
| 77 * | |
| 78 * Similar to the synchronous code, the error handler (registered with | |
| 79 * [catchError]) is handling the errors for exceptions coming from calls to | |
| 80 * 'foo', as well as 'bar'. This would not be the case if the error-handler was | |
| 81 * registered at the same time as the value-handler. | |
| 82 * | |
| 83 * Futures can have more than one callback-pairs registered. Each successor is | |
| 84 * treated independently and is handled as if it was the only successor. | |
| 29 */ | 85 */ |
| 86 // TODO(floitsch): document chaining. | |
| 30 abstract class Future<T> { | 87 abstract class Future<T> { |
| 31 /** A future whose value is immediately available. */ | 88 /** |
| 89 * A future whose value is immediately available. | |
|
nweiz
2013/01/11 19:55:06
This is a little misleading, since the event loop
floitsch
2013/01/11 20:46:09
Done.
| |
| 90 * | |
| 91 * See [Completer]s, for futures with values that are computed asynchronously. | |
| 92 */ | |
| 32 factory Future.immediate(T value) => new _FutureImpl<T>.immediate(value); | 93 factory Future.immediate(T value) => new _FutureImpl<T>.immediate(value); |
| 33 | 94 |
| 34 /** A future that completes with an error. */ | 95 /** |
| 96 * A future that completes with an error. | |
| 97 * | |
| 98 * See [Completer]s, for futures with values that are computed asynchronously. | |
| 99 */ | |
| 35 factory Future.immediateError(var error, [Object stackTrace]) { | 100 factory Future.immediateError(var error, [Object stackTrace]) { |
| 36 return new _FutureImpl<T>.immediateError(error, stackTrace); | 101 return new _FutureImpl<T>.immediateError(error, stackTrace); |
| 37 } | 102 } |
| 38 | 103 |
| 39 /** | 104 /** |
| 40 * Creates a future that completes after a delay. | 105 * Creates a future that completes after a delay. |
| 41 * | 106 * |
| 42 * The future will be completed after [milliseconds] have passed with | 107 * The future will be completed after [milliseconds] have passed with |
| 43 * the result of calling [value]. | 108 * the result of calling [value]. |
| 44 * | 109 * |
| 45 * If calling [value] throws, the created future will complete with the | 110 * If calling [value] throws, the created future will complete with the |
| 46 * error. | 111 * error. |
| 112 * | |
| 113 * See [Completer]s, for futures with values that are computed asynchronously. | |
| 47 */ | 114 */ |
| 48 factory Future.delayed(int milliseconds, T value()) { | 115 factory Future.delayed(int milliseconds, T value()) { |
| 49 _FutureImpl<T> future = new _ThenFuture<dynamic, T>((_) => value()); | 116 _FutureImpl<T> future = new _ThenFuture<dynamic, T>((_) => value()); |
| 50 new Timer(milliseconds, (_) => future._sendValue(null)); | 117 new Timer(milliseconds, (_) => future._sendValue(null)); |
| 51 return future; | 118 return future; |
| 52 } | 119 } |
| 53 | 120 |
| 54 /** | 121 /** |
| 55 * Wait for all the given futures to complete and collect their values. | 122 * Wait for all the given futures to complete and collect their values. |
| 56 * | 123 * |
| 57 * Returns a future which will complete once all the futures in a list are | 124 * Returns a future which will complete once all the futures in a list are |
| 58 * complete. If any of the futures in the list completes with an exception, | 125 * complete. If any of the futures in the list completes with an error, |
| 59 * the resulting future also completes with an exception. Otherwise the value | 126 * the resulting future also completes with an error. Otherwise the value |
| 60 * of the returned future will be a list of all the values that were produced. | 127 * of the returned future will be a list of all the values that were produced. |
| 61 */ | 128 */ |
| 62 static Future<List> wait(Iterable<Future> futures) { | 129 static Future<List> wait(Iterable<Future> futures) { |
| 63 return new _FutureImpl<List>.wait(futures); | 130 return new _FutureImpl<List>.wait(futures); |
| 64 } | 131 } |
| 65 | 132 |
| 66 /** | 133 /** |
| 67 * Perform an async operation for each element of the iterable, in turn. | 134 * Perform an async operation for each element of the iterable, in turn. |
| 68 * | 135 * |
| 69 * Runs [f] for each element in [input] in order, moving to the next element | 136 * Runs [f] for each element in [input] in order, moving to the next element |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 85 } | 152 } |
| 86 nextElement(null); | 153 nextElement(null); |
| 87 return doneSignal; | 154 return doneSignal; |
| 88 } | 155 } |
| 89 | 156 |
| 90 /** | 157 /** |
| 91 * When this future completes with a value, then [onValue] is called with this | 158 * When this future completes with a value, then [onValue] is called with this |
| 92 * value. If [this] future is already completed then the invocation of | 159 * value. If [this] future is already completed then the invocation of |
| 93 * [onValue] is delayed until the next event-loop iteration. | 160 * [onValue] is delayed until the next event-loop iteration. |
| 94 * | 161 * |
| 95 * Returns a new [Future] [:f:]. | 162 * Returns a new [Future] [:f:] which is completed with the result of |
|
nweiz
2013/01/11 19:55:06
I don't think Dartdoc's formatter understands "[Fu
floitsch
2013/01/11 20:46:09
Pretty sure it does. Will update if not.
nweiz
2013/01/11 21:39:06
You can see in the existing docs that it's not wor
floitsch
2013/01/11 22:39:48
Done.
| |
| 163 * invoking [onValue] (if [this] is completed with a value) or [onError] (if | |
| 164 * [this] is completed with an error). | |
| 96 * | 165 * |
| 97 * If [this] is completed with an error then [:f:] is completed with the same | 166 * If the invoked callback throws an exception, the returned future [:f:] is |
| 98 * error. If [this] is completed with a value, then [:f:]'s completion value | 167 * completed with the error. If the value thrown is an [AsyncError], it is |
| 99 * depends on the result of invoking [onValue] with [this]' completion value. | 168 * used directly, as the error result, otherwise it is wrapped in an |
|
nweiz
2013/01/11 19:55:06
Nit: "result, otherwise" -> "result. Otherwise"
floitsch
2013/01/11 20:46:09
Done.
| |
| 169 * [AsyncError] first. | |
| 100 * | 170 * |
| 101 * If [onValue] returns a [Future] [:f2:] then [:f:] and [:f2:] are chained. | 171 * If the invoked callback returns a [Future] [:f2:] then [:f:] and [:f2:] are |
| 102 * That is, [:f:] is completed with the completion value of [:f2:]. | 172 * chained. That is, [:f:] is completed with the completion value of [:f2:]. |
| 103 * | 173 * |
| 104 * Otherwise [:f:] is completed with the return value of [onValue]. | 174 * If [onError] is not given, it is equivalent to [:(e) { throw e; }:]. That |
| 105 * | 175 * is, it forwards the error. |
|
nweiz
2013/01/11 19:55:06
"forwards the error to the top-level exception han
floitsch
2013/01/11 20:46:09
No. to [:f:].
done.
| |
| 106 * If [onValue] throws an exception, the returned future will receive the | |
| 107 * exception. If the value thrown is an [AsyncError], it is used directly, | |
| 108 * as the error result, otherwise it is wrapped in an [AsyncError] first. | |
| 109 * | |
| 110 * If [onError] is provided, it is called if this future completes with an | |
| 111 * error, and its return value/throw behavior is handled the same way as | |
| 112 * for [catchError] without a [:test:] argument. | |
| 113 * | 176 * |
| 114 * In most cases, it is more readable to use [catchError] separately, possibly | 177 * In most cases, it is more readable to use [catchError] separately, possibly |
| 115 * with a [:test:] parameter, instead of handling both value and error in a | 178 * with a [:test:] parameter, instead of handling both value and error in a |
| 116 * single [then] call. | 179 * single [then] call. |
| 117 */ | 180 */ |
| 118 Future then(onValue(T value), { onError(AsyncError asyncError) }); | 181 Future then(onValue(T value), { onError(AsyncError asyncError) }); |
| 119 | 182 |
| 120 /** | 183 /** |
| 121 * Handles errors emitted by this [Future]. | 184 * Handles errors emitted by this [Future]. |
| 122 * | 185 * |
| 123 * When this future completes with an error, first [test] is called with the | 186 * When [this] completes with a value, the value is forwarded to [this]' |
|
nweiz
2013/01/11 19:55:06
Nit: "[this]'" -> "[this]'s"
floitsch
2013/01/11 20:46:09
Done.
| |
| 124 * error's value. | 187 * successor unmodified. |
|
nweiz
2013/01/11 19:55:06
It's confusing that in the documentation for then(
floitsch
2013/01/11 20:46:09
Done.
| |
| 125 * | 188 * |
| 126 * If [test] returns [true], [onError] is called with the error | 189 * When [this] completes with an error, [test] is called with the |
| 127 * wrapped in an [AsyncError]. The result of [onError] is handled exactly as | 190 * error's value. If the invocation returns [true], [onError] is called with |
| 128 * [then]'s [onValue]. | 191 * the error wrapped in an [AsyncError]. The result of [onError] is handled |
| 192 * exactly the same as for [then]'s [onError]. | |
| 129 * | 193 * |
| 130 * If [test] returns false, the exception is not handled by [onError], but is | 194 * If [test] returns false, the exception is not handled by [onError], but is |
| 131 * emitted by the returned Future unmodified. | 195 * thrown unmodified, thus passing it on [this]' successor. |
| 132 * | 196 * |
| 133 * If [test] is omitted, it defaults to a function that always returns true. | 197 * If [test] is omitted, it defaults to a function that always returns true. |
| 134 * | 198 * |
| 135 * Example: | 199 * Example: |
|
nweiz
2013/01/11 19:55:06
There should be a newline after this line, and the
floitsch
2013/01/11 20:46:09
Done.
| |
| 136 * foo | 200 * foo |
| 137 * .catchError(..., test: (e) => e is ArgumentError) | 201 * .catchError(..., test: (e) => e is ArgumentError) |
| 138 * .catchError(..., test: (e) => e is NoSuchMethodError) | 202 * .catchError(..., test: (e) => e is NoSuchMethodError) |
| 139 * .then((v) { ... }); | 203 * .then((v) { ... }); |
| 204 * | |
| 205 * This method is equivalent to: | |
| 206 * | |
| 207 * Future catchError(onError(AsyncError asyncError), | |
| 208 * {bool test(Object error)}) { | |
| 209 * this.then((v) => v, // Forward the value. | |
| 210 * // But handle errors, if the [test] succeeds. | |
| 211 * onError: (AsyncError e) { | |
| 212 * if (test == null || test(e.error)) { | |
| 213 * return onError(e); | |
| 214 * } | |
| 215 * throw e; | |
| 216 * }); | |
| 217 * } | |
| 218 * | |
| 140 */ | 219 */ |
| 141 Future catchError(onError(AsyncError asyncError), | 220 Future catchError(onError(AsyncError asyncError), |
| 142 {bool test(Object error)}); | 221 {bool test(Object error)}); |
| 143 | 222 |
| 144 /** | 223 /** |
| 145 * Register a function to be called when this future completes. | 224 * Register a function to be called when this future completes. |
| 146 * | 225 * |
| 147 * The [action] function is called when this future completes, whether it | 226 * The [action] function is called when this future completes, whether it |
| 148 * does so with a value or with an error. | 227 * does so with a value or with an error. |
| 149 * | 228 * |
| 150 * This is the asynchronous equivalent of a "finally" block. | 229 * This is the asynchronous equivalent of a "finally" block. |
| 151 * | 230 * |
| 152 * The future returned by this call, [:f:], will complete the same way | 231 * The future returned by this call, [:f:], will complete the same way |
| 153 * as this future unless an error occurs in the [action] call, or in | 232 * as this future unless an error occurs in the [action] call, or in |
| 154 * a [Future] returned by the [action] call. If the call to [action] | 233 * a [Future] returned by the [action] call. If the call to [action] |
| 155 * does not return a future, its return value is ignored. | 234 * does not return a future, its return value is ignored. |
| 156 * | 235 * |
| 157 * If the call to [action] throws, then [:f:] is completed with the | 236 * If the call to [action] throws, then [:f:] is completed with the |
| 158 * thrown error. | 237 * thrown error. |
| 159 * | 238 * |
| 160 * If the call to [action] returns a [Future], [:f2:], then completion of | 239 * If the call to [action] returns a [Future], [:f2:], then completion of |
| 161 * [:f:] is delayed until [:f2:] completes. If [:f2:] completes with | 240 * [:f:] is delayed until [:f2:] completes. If [:f2:] completes with |
| 162 * an error, that will be the result of [:f:] too. | 241 * an error, that will be the result of [:f:] too. |
| 242 * | |
| 243 * This method is equivalent to: | |
| 244 * | |
| 245 * Future<T> whenComplete(action()) { | |
| 246 * this.then((v) { | |
| 247 * action(); | |
| 248 * return v | |
| 249 * }, | |
| 250 * onError: (AsyncError e) { | |
|
nweiz
2013/01/11 19:55:06
This is another place where it would be nice to us
floitsch
2013/01/11 20:46:09
Not possible, since it would change the semantics.
nweiz
2013/01/11 21:39:06
Not if catchError() comes before then().
floitsch
2013/01/11 22:39:48
point taken.
For now I will leave it as is. I will
| |
| 251 * action(); | |
| 252 * throw e; | |
| 253 * }); | |
| 254 * } | |
| 163 */ | 255 */ |
| 164 Future<T> whenComplete(action()); | 256 Future<T> whenComplete(action()); |
| 165 | 257 |
| 166 /** | 258 /** |
| 167 * Creates a [Stream] that sends [this]' completion value, data or error, to | 259 * Creates a [Stream] that sends [this]' completion value, data or error, to |
| 168 * its subscribers. The stream closes after the completion value. | 260 * its subscribers. The stream closes after the completion value. |
| 169 */ | 261 */ |
| 170 Stream<T> asStream(); | 262 Stream<T> asStream(); |
| 171 } | 263 } |
| 172 | 264 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 213 * The argument [exception] should not be [:null:]. | 305 * The argument [exception] should not be [:null:]. |
| 214 * | 306 * |
| 215 * If [exception] is an [AsyncError], it is used directly as the error | 307 * If [exception] is an [AsyncError], it is used directly as the error |
| 216 * message sent to the future's listeners, and [stackTrace] is ignored. | 308 * message sent to the future's listeners, and [stackTrace] is ignored. |
| 217 * | 309 * |
| 218 * Otherwise the [exception] and an optional [stackTrace] is combined into an | 310 * Otherwise the [exception] and an optional [stackTrace] is combined into an |
| 219 * [AsyncError] and sent to this future's listeners. | 311 * [AsyncError] and sent to this future's listeners. |
| 220 */ | 312 */ |
| 221 void completeError(Object exception, [Object stackTrace]); | 313 void completeError(Object exception, [Object stackTrace]); |
| 222 } | 314 } |
| OLD | NEW |