Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: sdk/lib/async/future.dart

Issue 11852027: Improve documentation for futures. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698