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

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

Issue 2917683002: Clean-up of Future documentation and small fix-ups. (Closed)
Patch Set: Created 3 years, 6 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
« no previous file with comments | « no previous file | sdk/lib/async/stream.dart » ('j') | 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 /// A type representing values that are either `Future<T>` or `T`. 7 /// A type representing values that are either `Future<T>` or `T`.
8 /// 8 ///
9 /// This class declaration is a public stand-in for an internal 9 /// This class declaration is a public stand-in for an internal
10 /// future-or-value generic type. References to this class are resolved to the 10 /// future-or-value generic type. References to this class are resolved to the
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 * A [Future] is used to represent a potential value, or error, 50 * A [Future] is used to represent a potential value, or error,
51 * that will be available at some time in the future. 51 * that will be available at some time in the future.
52 * Receivers of a [Future] can register callbacks 52 * Receivers of a [Future] can register callbacks
53 * that handle the value or error once it is available. 53 * that handle the value or error once it is available.
54 * For example: 54 * For example:
55 * 55 *
56 * Future<int> future = getFuture(); 56 * Future<int> future = getFuture();
57 * future.then((value) => handleValue(value)) 57 * future.then((value) => handleValue(value))
58 * .catchError((error) => handleError(error)); 58 * .catchError((error) => handleError(error));
59 * 59 *
60 * A [Future] can complete in two ways: 60 * A [Future] can be completed in two ways:
61 * with a value ("the future succeeds") 61 * with a value ("the future succeeds")
62 * or with an error ("the future fails"). 62 * or with an error ("the future fails").
63 * Users can install callbacks for each case. 63 * Users can install callbacks for each case.
64 * In some cases we say that a future is completed with another future.
floitsch 2017/05/31 15:28:27 Put a line before here. (I think this should be a
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Done.
65 * In that case, the other future is waited for, and when it completes,
floitsch 2017/05/31 15:28:27 ... with another future. This is a short way of st
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Used with slight rewording.
66 * the first future is completed in the same way, with the same value or error.
67 *
64 * The result of registering a pair of callbacks is a new Future (the 68 * The result of registering a pair of callbacks is a new Future (the
65 * "successor") which in turn is completed with the result of invoking the 69 * "successor") which in turn is completed with the result of invoking the
66 * corresponding callback. 70 * corresponding callback.
67 * The successor is completed with an error if the invoked callback throws. 71 * The successor is completed with an error if the invoked callback throws.
68 * For example: 72 * For example:
69 * 73 * ```
70 * Future<int> successor = future.then((int value) { 74 * Future<int> successor = future.then((int value) {
71 * // Invoked when the future is completed with a value. 75 * // Invoked when the future is completed with a value.
72 * return 42; // The successor is completed with the value 42. 76 * return 42; // The successor is completed with the value 42.
73 * }, 77 * },
74 * onError: (e) { 78 * onError: (e) {
75 * // Invoked when the future is completed with an error. 79 * // Invoked when the future is completed with an error.
76 * if (canHandle(e)) { 80 * if (canHandle(e)) {
77 * return 499; // The successor is completed with the value 499. 81 * return 499; // The successor is completed with the value 499.
78 * } else { 82 * } else {
79 * throw e; // The successor is completed with the error e. 83 * throw e; // The successor is completed with the error e.
80 * } 84 * }
81 * }); 85 * });
86 * ```
82 * 87 *
83 * If a future does not have a successor when it completes with an error, 88 * If a future does not have a successor when it completes with an error,
84 * it forwards the error message to the global error-handler. 89 * it forwards the error message to the global error-handler.
85 * This behavior makes sure that no error is silently dropped. 90 * This behavior makes sure that no error is silently dropped.
86 * However, it also means that error handlers should be installed early, 91 * However, it also means that error handlers should be installed early,
87 * so that they are present as soon as a future is completed with an error. 92 * so that they are present as soon as a future is completed with an error.
88 * The following example demonstrates this potential bug: 93 * The following example demonstrates this potential bug:
89 * 94 * ```
90 * var future = getFuture(); 95 * var future = getFuture();
91 * new Timer(new Duration(milliseconds: 5), () { 96 * new Timer(new Duration(milliseconds: 5), () {
92 * // The error-handler is not attached until 5 ms after the future has 97 * // The error-handler is not attached until 5 ms after the future has
93 * // been received. If the future fails before that, the error is 98 * // been received. If the future fails before that, the error is
94 * // forwarded to the global error-handler, even though there is code 99 * // forwarded to the global error-handler, even though there is code
95 * // (just below) to eventually handle the error. 100 * // (just below) to eventually handle the error.
96 * future.then((value) { useValue(value); }, 101 * future.then((value) { useValue(value); },
97 * onError: (e) { handleError(e); }); 102 * onError: (e) { handleError(e); });
98 * }); 103 * });
104 * ```
99 * 105 *
100 * When registering callbacks, it's often more readable to register the two 106 * When registering callbacks, it's often more readable to register the two
101 * callbacks separately, by first using [then] with one argument 107 * callbacks separately, by first using [then] with one argument
102 * (the value handler) and using a second [catchError] for handling errors. 108 * (the value handler) and using a second [catchError] for handling errors.
103 * Each of these will forward the result that they don't handle 109 * Each of these will forward the result that they don't handle
104 * to their successors, and together they handle both value and error result. 110 * to their successors, and together they handle both value and error result.
105 * It also has the additional benefit of the [catchError] handling errors in the 111 * It also has the additional benefit of the [catchError] handling errors in the
106 * [then] value callback too. 112 * [then] value callback too.
107 * Using sequential handlers instead of parallel ones often leads to code that 113 * Using sequential handlers instead of parallel ones often leads to code that
108 * is easier to reason about. 114 * is easier to reason about.
109 * It also makes asynchronous code very similar to synchronous code: 115 * It also makes asynchronous code very similar to synchronous code:
110 * 116 * ```
111 * // Synchronous code. 117 * // Synchronous code.
112 * try { 118 * try {
113 * int value = foo(); 119 * int value = foo();
114 * return bar(value); 120 * return bar(value);
115 * } catch (e) { 121 * } catch (e) {
116 * return 499; 122 * return 499;
117 * } 123 * }
124 * ```
118 * 125 *
119 * Equivalent asynchronous code, based on futures: 126 * Equivalent asynchronous code, based on futures:
120 * 127 * ```
121 * Future<int> future = new Future(foo); // Result of foo() as a future. 128 * Future<int> future = new Future(foo); // Result of foo() as a future.
122 * future.then((int value) => bar(value)) 129 * future.then((int value) => bar(value))
123 * .catchError((e) => 499); 130 * .catchError((e) => 499);
131 * ```
124 * 132 *
125 * Similar to the synchronous code, the error handler (registered with 133 * Similar to the synchronous code, the error handler (registered with
126 * [catchError]) is handling any errors thrown by either `foo` or `bar`. 134 * [catchError]) is handling any errors thrown by either `foo` or `bar`.
127 * If the error-handler had been registered as the `onError` parameter of 135 * If the error-handler had been registered as the `onError` parameter of
128 * the `then` call, it would not catch errors from the `bar` call. 136 * the `then` call, it would not catch errors from the `bar` call.
129 * 137 *
130 * Futures can have more than one callback-pair registered. Each successor is 138 * Futures can have more than one callback-pair registered. Each successor is
131 * treated independently and is handled as if it was the only successor. 139 * treated independently and is handled as if it was the only successor.
132 * 140 *
133 * A future may also fail to ever complete. In that case, no callbacks are 141 * A future may also fail to ever complete. In that case, no callbacks are
134 * called. 142 * called.
135 */ 143 */
136 abstract class Future<T> { 144 abstract class Future<T> {
137 // The `_nullFuture` is a completed Future with the value `null`. 145 /// A `Future<Null>` completed with `null`.
floitsch 2017/05/31 15:28:27 Should we make this one public? It's quite common.
Lasse Reichstein Nielsen 2017/06/02 05:53:39 I'd want to iterate a little on the name if we mak
138 static final _Future<Null> _nullFuture = new _Future<Null>.value(null); 146 static final _Future<Null> _nullFuture = new _Future<Null>.value(null);
139 147
148 /// A `Future<bool>` completed with `false`.
149 static final _Future<bool> _falseFuture = new _Future<bool>.value(false);
150
140 /** 151 /**
141 * Creates a future containing the result of calling [computation] 152 * Creates a future containing the result of calling [computation]
142 * asynchronously with [Timer.run]. 153 * asynchronously with [Timer.run].
143 * 154 *
144 * If the result of executing [computation] throws, the returned future is 155 * If the result of executing [computation] throws, the returned future is
145 * completed with the error. 156 * completed with the error.
146 * 157 *
147 * If the returned value is itself a [Future], completion of 158 * If the returned value is itself a [Future], completion of
148 * the created future will wait until the returned future completes, 159 * the created future will wait until the returned future completes,
149 * and will then complete with the same result. 160 * and will then complete with the same result.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 future._asyncCompleteError( 230 future._asyncCompleteError(
220 _nonNullError(replacement.error), replacement.stackTrace); 231 _nonNullError(replacement.error), replacement.stackTrace);
221 } else { 232 } else {
222 future._asyncCompleteError(error, stackTrace); 233 future._asyncCompleteError(error, stackTrace);
223 } 234 }
224 return future; 235 return future;
225 } 236 }
226 } 237 }
227 238
228 /** 239 /**
229 * A future whose value is available in the next event-loop iteration. 240 * Creates a future completed with [result].
floitsch 2017/05/31 15:28:27 a future, completed with...
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Don't think that would work, there'd be no subject
230 * 241 *
231 * If [result] is not a [Future], using this constructor is equivalent 242 * If [result] is a future, this creates a new future that waits for the
floitsch 2017/05/31 15:28:28 "this creates" sounds bad. The created future wai
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Done.
232 * to `new Future<T>.sync(() => result)`. 243 * [result] future to complete, and then completes with the same result.
floitsch 2017/05/31 15:28:27 Maybe mention that this means that a Future.value
244 *
245 * If [result] is not a [Future], this creates a future that is already
floitsch 2017/05/31 15:28:27 not a [Future], the returned future
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Done + reworded.
246 * completed with th [result] value
floitsch 2017/05/31 15:28:28 the
Lasse Reichstein Nielsen 2017/06/02 05:53:38 Done.
247 * equivalent to `new Future<T>.sync(() => result)`.
233 * 248 *
234 * Use [Completer] to create a future and complete it later. 249 * Use [Completer] to create a future and complete it later.
235 */ 250 */
236 factory Future.value([FutureOr<T> result]) { 251 factory Future.value([FutureOr<T> result]) {
floitsch 2017/05/31 15:28:27 "result" sounds weird. Probably just "value"?
Lasse Reichstein Nielsen 2017/06/02 05:53:38 Done.
237 return new _Future<T>.immediate(result); 252 return new _Future<T>.immediate(result);
238 } 253 }
239 254
240 /** 255 /**
241 * A future that completes with an error in the next event-loop iteration. 256 * Creates a future that completes with an error.
257 *
258 * The created future will be completed with an error in a future microtask.
259 * This allows enough time for someone to add an error handler on the future.
260 * If an error handler isn't added before the future completes, the error
261 * will be considered unhandled.
242 * 262 *
243 * If [error] is `null`, it is replaced by a [NullThrownError]. 263 * If [error] is `null`, it is replaced by a [NullThrownError].
244 * 264 *
245 * Use [Completer] to create a future and complete it later. 265 * Use [Completer] to create a future and complete it later.
246 */ 266 */
247 factory Future.error(Object error, [StackTrace stackTrace]) { 267 factory Future.error(Object error, [StackTrace stackTrace]) {
248 error = _nonNullError(error); 268 error = _nonNullError(error);
249 if (!identical(Zone.current, _ROOT_ZONE)) { 269 if (!identical(Zone.current, _ROOT_ZONE)) {
250 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); 270 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
251 if (replacement != null) { 271 if (replacement != null) {
252 error = _nonNullError(replacement.error); 272 error = _nonNullError(replacement.error);
253 stackTrace = replacement.stackTrace; 273 stackTrace = replacement.stackTrace;
254 } 274 }
255 } 275 }
256 return new _Future<T>.immediateError(error, stackTrace); 276 return new _Future<T>.immediateError(error, stackTrace);
257 } 277 }
258 278
259 /** 279 /**
260 * Creates a future that runs its computation after a delay. 280 * Creates a future that runs its computation after a delay.
261 * 281 *
262 * The [computation] will be executed after the given [duration] has passed, 282 * The [computation] will be executed after the given [duration] has passed,
263 * and the future is completed with the result. 283 * and the future is completed with the result of the computation,
284 *
264 * If the duration is 0 or less, 285 * If the duration is 0 or less,
265 * it completes no sooner than in the next event-loop iteration. 286 * it completes no sooner than in the next event-loop iteration,
287 * after microtasks have run.
floitsch 2017/05/31 15:28:27 after all microtasks
Lasse Reichstein Nielsen 2017/06/02 05:53:39 OK, but technically not correct - there might be m
266 * 288 *
267 * If [computation] is omitted, 289 * If [computation] is omitted,
268 * it will be treated as if [computation] was set to `() => null`, 290 * it will be treated as if [computation] was `() => null`,
269 * and the future will eventually complete with the `null` value. 291 * and the future will eventually complete with the `null` value.
270 * 292 *
271 * If calling [computation] throws, the created future will complete with the 293 * If calling [computation] throws, the created future will complete with the
272 * error. 294 * error.
273 * 295 *
274 * See also [Completer] for a way to create and complete a future at a 296 * See also [Completer] for a way to create and complete a future at a
275 * later time that isn't necessarily after a known fixed duration. 297 * later time that isn't necessarily after a known fixed duration.
276 */ 298 */
277 factory Future.delayed(Duration duration, [FutureOr<T> computation()]) { 299 factory Future.delayed(Duration duration, [FutureOr<T> computation()]) {
278 _Future<T> result = new _Future<T>(); 300 _Future<T> result = new _Future<T>();
279 new Timer(duration, () { 301 new Timer(duration, () {
280 try { 302 try {
281 result._complete(computation?.call()); 303 result._complete(computation?.call());
282 } catch (e, s) { 304 } catch (e, s) {
283 _completeWithErrorCallback(result, e, s); 305 _completeWithErrorCallback(result, e, s);
284 } 306 }
285 }); 307 });
286 return result; 308 return result;
287 } 309 }
288 310
289 /** 311 /**
290 * Wait for all the given futures to complete and collect their values. 312 * Waits for multiple futures to complete and collects their results.
291 * 313 *
292 * Returns a future which will complete once all the futures in a list 314 * Returns a future which will complete once all the provided futures
293 * have completed. 315 * have completed, either with their results, or with an error if either
316 * of the provided futures fail.
294 * 317 *
295 * The value of the returned future will be a list of all the values that 318 * The value of the returned future will be a list of all the values that
296 * were produced. 319 * were produced.
297 * 320 *
298 * If any of the given futures completes with an error, then the returned 321 * If any future completes with an error,
299 * future completes with that error. If other futures complete with errors, 322 * then the returned future completes with that error.
300 * those errors are discarded. 323 * If further futures also complete with errors, those errors are discarded.
301 * 324 *
302 * If `eagerError` is true, the returned future completes with an error 325 * If `eagerError` is true, the returned future completes with an error
303 * immediately on the first error from one of the futures. Otherwise all 326 * immediately on the first error from one of the futures. Otherwise all
304 * futures must complete before the returned future is completed (still with 327 * futures must complete before the returned future is completed (still with
305 * the first error; the remaining errors are silently dropped). 328 * the first error; the remaining errors are silently dropped).
306 * 329 *
307 * In the case of an error, [cleanUp] (if provided), is invoked on any 330 * In the case of an error, [cleanUp] (if provided), is invoked on any
308 * non-null result of successful futures. 331 * non-null result of successful futures.
309 * This makes it posible to `cleanUp` resources that would otherwise be 332 * This makes it posible to "clean up" resources that would otherwise be
310 * lost (since the returned future does not provide access to these values). 333 * lost since the returned future does not provide access to these values.
311 * The [cleanup] function is unused if there is no error. 334 * The [cleanUp] function is unused if there is no error.
312 * 335 *
313 * The call to `cleanUp` should not throw. If it does, the error will be an 336 * The call to [cleanUp] should not throw. If it does, the error will be an
314 * uncaught asynchronous error. 337 * uncaught asynchronous error.
315 */ 338 */
316 static Future<List<T>> wait<T>(Iterable<Future<T>> futures, 339 static Future<List<T>> wait<T>(Iterable<Future<T>> futures,
317 {bool eagerError: false, void cleanUp(T successValue)}) { 340 {bool eagerError: false, void cleanUp(T successValue)}) {
318 final _Future<List<T>> result = new _Future<List<T>>(); 341 final _Future<List<T>> result = new _Future<List<T>>();
319 List<T> values; // Collects the values. Set to null on error. 342 List<T> values; // Collects the values. Set to null on error.
320 int remaining = 0; // How many futures are we waiting for. 343 int remaining = 0; // How many futures are we waiting for.
321 var error; // The first error from a future. 344 var error; // The first error from a future.
322 StackTrace stackTrace; // The stackTrace that came with the error. 345 StackTrace stackTrace; // The stackTrace that came with the error.
323 346
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 stackTrace = st; 424 stackTrace = st;
402 } 425 }
403 } 426 }
404 return result; 427 return result;
405 } 428 }
406 429
407 /** 430 /**
408 * Returns the result of the first future in [futures] to complete. 431 * Returns the result of the first future in [futures] to complete.
409 * 432 *
410 * The returned future is completed with the result of the first 433 * The returned future is completed with the result of the first
411 * future in [futures] to report that it is complete. 434 * future in [futures] to report that it is complete,
435 * whether it's with a value or an error.
412 * The results of all the other futures are discarded. 436 * The results of all the other futures are discarded.
413 * 437 *
414 * If [futures] is empty, or if none of its futures complete, 438 * If [futures] is empty, or if none of its futures complete,
415 * the returned future never completes. 439 * the returned future never completes.
416 */ 440 */
417 static Future<T> any<T>(Iterable<Future<T>> futures) { 441 static Future<T> any<T>(Iterable<Future<T>> futures) {
418 var completer = new Completer<T>.sync(); 442 var completer = new Completer<T>.sync();
419 var onValue = (T value) { 443 var onValue = (T value) {
420 if (!completer.isCompleted) completer.complete(value); 444 if (!completer.isCompleted) completer.complete(value);
421 }; 445 };
422 var onError = (error, stack) { 446 var onError = (error, stack) {
423 if (!completer.isCompleted) completer.completeError(error, stack); 447 if (!completer.isCompleted) completer.completeError(error, stack);
424 }; 448 };
425 for (var future in futures) { 449 for (var future in futures) {
426 future.then(onValue, onError: onError); 450 future.then(onValue, onError: onError);
427 } 451 }
428 return completer.future; 452 return completer.future;
429 } 453 }
430 454
431 /** 455 /**
432 * Perform an operation for each element of the iterable, in turn. 456 * Performs an action for each element of the iterable, in turn.
433 * 457 *
434 * The operation, [f], may be either synchronous or asynchronous. 458 * The [action] may be either synchronous or asynchronous.
435 * 459 *
436 * Calls [f] with each element in [input] in order. 460 * Calls [action] with each element in [elements] in order.
437 * If the call to [f] returns a `Future<T>`, the iteration waits 461 * If the call to [action] returns a `Future<T>`, the iteration waits
438 * until the future is completed before moving to the next element. 462 * until the future is completed before continuing with the next element.
439 * 463 *
440 * Returns a [Future] that completes with `null` when all elements have been 464 * Returns a [Future] that completes with `null` when all elements have been
441 * processed. 465 * processed.
442 * 466 *
443 * Non-[Future] return values, and completion-values of returned [Future]s, 467 * Non-[Future] return values, and completion-values of returned [Future]s,
444 * are discarded. 468 * are discarded.
445 * 469 *
446 * Any error from [f], synchronous or asynchronous, will stop the iteration 470 * Any error from [action], synchronous or asynchronous,
447 * and will be reported in the returned [Future]. 471 * will stop the iteration and be reported in the returned [Future].
448 */ 472 */
449 static Future forEach<T>(Iterable<T> input, FutureOr f(T element)) { 473 static Future forEach<T>(Iterable<T> elements, FutureOr action(T element)) {
450 var iterator = input.iterator; 474 var iterator = elements.iterator;
451 return doWhile(() { 475 return doWhile(() {
452 if (!iterator.moveNext()) return false; 476 if (!iterator.moveNext()) return false;
453 var result = f(iterator.current); 477 var result = action(iterator.current);
454 if (result is Future) return result.then(_kTrue); 478 if (result is Future) return result.then(_kTrue);
455 return true; 479 return true;
456 }); 480 });
457 } 481 }
458 482
459 // Constant `true` function, used as callback by [forEach]. 483 // Constant `true` function, used as callback by [forEach].
460 static bool _kTrue(_) => true; 484 static bool _kTrue(_) => true;
461 485
462 /** 486 /**
463 * Performs an operation repeatedly until it returns `false`. 487 * Performs an operation repeatedly until it returns `false`.
464 * 488 *
465 * The operation, [f], may be either synchronous or asynchronous. 489 * The operation, [f], may be either synchronous or asynchronous.
466 * 490 *
467 * The operation is called repeatedly as long as it returns either the [bool] 491 * The operation is called repeatedly as long as it returns either the [bool]
468 * value `true` or a `Future<bool>` which completes with the value `true`. 492 * value `true` or a `Future<bool>` which completes with the value `true`.
469 * 493 *
470 * If a call to [f] returns `false` or a [Future] that completes to `false`, 494 * If a call to [f] returns `false` or a [Future] that completes to `false`,
471 * iteration ends and the future returned by [doWhile] is completed with 495 * iteration ends and the future returned by [doWhile] is completed with
472 * a `null` value. 496 * a `null` value.
473 * 497 *
474 * If a call to [f] throws or a future returned by [f] completes with 498 * If a call to [f] throws or a future returned by [f] completes with
475 * an error, iteration ends and the future returned by [doWhile] 499 * an error, iteration ends and the future returned by [doWhile]
476 * completes with the same error. 500 * completes with the same error.
477 * 501 *
478 * Calls to [f] may happen at any time, including immediately after calling 502 * Calls to [action] may happen at any time,
479 * `doWhile`. The only restriction is a new call to [f] won't happen before 503 * including immediately after calling `doWhile`.
504 * The only restriction is a new call to [action] won't happen before
480 * the previous call has returned, and if it returned a `Future<bool>`, not 505 * the previous call has returned, and if it returned a `Future<bool>`, not
481 * until that future has completed. 506 * until that future has completed.
482 */ 507 */
483 static Future doWhile(FutureOr<bool> f()) { 508 static Future doWhile(FutureOr<bool> action()) {
484 _Future doneSignal = new _Future(); 509 _Future doneSignal = new _Future();
485 var nextIteration; 510 var nextIteration;
486 // Bind this callback explicitly so that each iteration isn't bound in the 511 // Bind this callback explicitly so that each iteration isn't bound in the
487 // context of all the previous iterations' callbacks. 512 // context of all the previous iterations' callbacks.
488 // This avoids, e.g., deeply nested stack traces from the stack trace 513 // This avoids, e.g., deeply nested stack traces from the stack trace
489 // package. 514 // package.
490 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { 515 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) {
491 while (keepGoing) { 516 while (keepGoing) {
492 FutureOr<bool> result; 517 FutureOr<bool> result;
493 try { 518 try {
494 result = f(); 519 result = action();
495 } catch (error, stackTrace) { 520 } catch (error, stackTrace) {
496 // Cannot use _completeWithErrorCallback because it completes 521 // Cannot use _completeWithErrorCallback because it completes
497 // the future synchronously. 522 // the future synchronously.
498 _asyncCompleteWithErrorCallback(doneSignal, error, stackTrace); 523 _asyncCompleteWithErrorCallback(doneSignal, error, stackTrace);
499 return; 524 return;
500 } 525 }
501 if (result is Future<bool>) { 526 if (result is Future<bool>) {
502 result.then(nextIteration, onError: doneSignal._completeError); 527 result.then(nextIteration, onError: doneSignal._completeError);
503 return; 528 return;
504 } 529 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 * If `test` is omitted, it defaults to a function that always returns true. 607 * If `test` is omitted, it defaults to a function that always returns true.
583 * The `test` function should not throw, but if it does, it is handled as 608 * The `test` function should not throw, but if it does, it is handled as
584 * if the `onError` function had thrown. 609 * if the `onError` function had thrown.
585 * 610 *
586 * Note that futures don't delay reporting of errors until listeners are 611 * Note that futures don't delay reporting of errors until listeners are
587 * added. If the first `catchError` (or `then`) call happens after this future 612 * added. If the first `catchError` (or `then`) call happens after this future
588 * has completed with an error then the error is reported as unhandled error. 613 * has completed with an error then the error is reported as unhandled error.
589 * See the description on [Future]. 614 * See the description on [Future].
590 * 615 *
591 * Example: 616 * Example:
592 * 617 * ```
floitsch 2017/05/31 15:28:28 I would just remove this example. Way too complica
Lasse Reichstein Nielsen 2017/06/02 05:53:38 Removed.
593 * foo 618 * foo
594 * .catchError(..., test: (e) => e is ArgumentError) 619 * .catchError(..., test: (e) => e is ArgumentError)
595 * .catchError(..., test: (e) => e is NoSuchMethodError) 620 * .catchError(..., test: (e) => e is NoSuchMethodError)
596 * .then((v) { ... }); 621 * .then((v) { ... });
622 * ```
597 * 623 *
598 * This method is equivalent to: 624 * This method is equivalent to:
599 * 625 * ```
600 * Future catchError(onError(error), 626 * Future catchError(onError(error),
601 * {bool test(error)}) { 627 * {bool test(error)}) {
602 * this.then((v) => v, // Forward the value. 628 * this.then((v) => v, // Forward the value.
603 * // But handle errors, if the [test] succeeds. 629 * // But handle errors, if the [test] succeeds.
604 * onError: (e, stackTrace) { 630 * onError: (e, stackTrace) {
605 * if (test == null || test(e)) { 631 * if (test == null || test(e)) {
606 * if (onError is ZoneBinaryCallback) { 632 * if (onError is ZoneBinaryCallback) {
607 * return onError(e, stackTrace); 633 * return onError(e, stackTrace);
608 * } 634 * }
609 * return onError(e); 635 * return onError(e);
610 * } 636 * }
611 * throw e; 637 * throw e;
612 * }); 638 * });
613 * } 639 * }
614 * 640 * ```
615 */ 641 */
616 // The `Function` below stands for one of two types: 642 // The `Function` below stands for one of two types:
617 // - (dynamic) -> FutureOr<T> 643 // - (dynamic) -> FutureOr<T>
618 // - (dynamic, StackTrace) -> FutureOr<T> 644 // - (dynamic, StackTrace) -> FutureOr<T>
619 // Given that there is a `test` function that is usually used to do an 645 // Given that there is a `test` function that is usually used to do an
620 // `isCheck` we should also expect functions that take a specific argument. 646 // `isCheck` we should also expect functions that take a specific argument.
621 // Note: making `catchError` return a `Future<T>` in non-strong mode could be 647 // Note: making `catchError` return a `Future<T>` in non-strong mode could be
622 // a breaking change. 648 // a breaking change.
623 Future<T> catchError(Function onError, {bool test(Object error)}); 649 Future<T> catchError(Function onError, {bool test(Object error)});
624 650
625 /** 651 /**
626 * Register a function to be called when this future completes. 652 * Registers a function to be called when this future completes.
627 * 653 *
628 * The [action] function is called when this future completes, whether it 654 * The [action] function is called when this future completes, whether it
629 * does so with a value or with an error. 655 * does so with a value or with an error.
630 * 656 *
631 * This is the asynchronous equivalent of a "finally" block. 657 * This is the asynchronous equivalent of a "finally" block.
632 * 658 *
633 * The future returned by this call, `f`, will complete the same way 659 * The future returned by this call, `f`, will complete the same way
634 * as this future unless an error occurs in the [action] call, or in 660 * as this future unless an error occurs in the [action] call, or in
635 * a [Future] returned by the [action] call. If the call to [action] 661 * a [Future] returned by the [action] call. If the call to [action]
636 * does not return a future, its return value is ignored. 662 * does not return a future, its return value is ignored.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 } 732 }
707 } 733 }
708 734
709 /** 735 /**
710 * A way to produce Future objects and to complete them later 736 * A way to produce Future objects and to complete them later
711 * with a value or error. 737 * with a value or error.
712 * 738 *
713 * Most of the time, the simplest way to create a future is to just use 739 * Most of the time, the simplest way to create a future is to just use
714 * one of the [Future] constructors to capture the result of a single 740 * one of the [Future] constructors to capture the result of a single
715 * asynchronous computation: 741 * asynchronous computation:
716 * 742 * ```
717 * new Future(() { doSomething(); return result; }); 743 * new Future(() { doSomething(); return result; });
718 * 744 * ```
719 * or, if the future represents the result of a sequence of asynchronous 745 * or, if the future represents the result of a sequence of asynchronous
720 * computations, they can be chained using [Future.then] or similar functions 746 * computations, they can be chained using [Future.then] or similar functions
721 * on [Future]: 747 * on [Future]:
722 * 748 * ```
723 * Future doStuff(){ 749 * Future doStuff(){
724 * return someAsyncOperation().then((result) { 750 * return someAsyncOperation().then((result) {
725 * return someOtherAsyncOperation(result); 751 * return someOtherAsyncOperation(result);
726 * }); 752 * });
727 * } 753 * }
728 * 754 * ```
729 * If you do need to create a Future from scratch — for example, 755 * If you do need to create a Future from scratch — for example,
730 * when you're converting a callback-based API into a Future-based 756 * when you're converting a callback-based API into a Future-based
731 * one — you can use a Completer as follows: 757 * one — you can use a Completer as follows:
758 * ```
759 * class AsyncOperation {
760 * Completer _completer = new Completer();
732 * 761 *
733 * class AsyncOperation { 762 * Future<T> doOperation() {
734 * Completer _completer = new Completer(); 763 * _startOperation();
764 * return _completer.future; // Send future object back to client.
765 * }
735 * 766 *
736 * Future<T> doOperation() { 767 * // Something calls this when the value is ready.
737 * _startOperation(); 768 * void _finishOperation(T result) {
738 * return _completer.future; // Send future object back to client. 769 * _completer.complete(result);
739 * } 770 * }
740 * 771 *
741 * // Something calls this when the value is ready. 772 * // If something goes wrong, call this.
742 * void _finishOperation(T result) { 773 * void _errorHappened(error) {
743 * _completer.complete(result); 774 * _completer.completeError(error);
744 * } 775 * }
745 * 776 * }
746 * // If something goes wrong, call this. 777 * ```
747 * void _errorHappened(error) {
748 * _completer.completeError(error);
749 * }
750 * }
751 */ 778 */
752 abstract class Completer<T> { 779 abstract class Completer<T> {
753 /** 780 /**
754 * Creates a new completer. 781 * Creates a new completer.
755 * 782 *
756 * The general workflow for creating a new future is to 1) create a 783 * The general workflow for creating a new future is to 1) create a
757 * new completer, 2) hand out its future, and, at a later point, 3) invoke 784 * new completer, 2) hand out its future, and, at a later point, 3) invoke
758 * either [complete] or [completeError]. 785 * either [complete] or [completeError].
759 * 786 *
760 * The completer completes the future asynchronously. That means that 787 * The completer completes the future asynchronously. That means that
761 * callbacks registered on the future, are not called immediately when 788 * callbacks registered on the future are not called immediately when
762 * [complete] or [completeError] is called. Instead the callbacks are 789 * [complete] or [completeError] is called. Instead the callbacks are
763 * delayed until a later microtask. 790 * delayed until a later microtask.
764 * 791 *
765 * Example: 792 * Example:
766 * 793 * ```
767 * var completer = new Completer(); 794 * var completer = new Completer();
768 * handOut(completer.future); 795 * handOut(completer.future);
769 * later: { 796 * later: {
770 * completer.complete('completion value'); 797 * completer.complete('completion value');
771 * } 798 * }
799 * ```
772 */ 800 */
773 factory Completer() => new _AsyncCompleter<T>(); 801 factory Completer() => new _AsyncCompleter<T>();
774 802
775 /** 803 /**
776 * Completes the future synchronously. 804 * Completes the future synchronously.
777 * 805 *
778 * This constructor should be avoided unless the completion of the future is 806 * This constructor should be avoided unless the completion of the future is
779 * known to be the final result of another asynchronous operation. If in doubt 807 * known to be the final result of another asynchronous operation. If in doubt
780 * use the default [Completer] constructor. 808 * use the default [Completer] constructor.
781 * 809 *
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 * // The completion is the result of the asynchronous onDone event. 845 * // The completion is the result of the asynchronous onDone event.
818 * // However, there is still code executed after the completion. This 846 * // However, there is still code executed after the completion. This
819 * // operation is *not* safe. 847 * // operation is *not* safe.
820 * stream.listen(print, onDone: () { 848 * stream.listen(print, onDone: () {
821 * completer.complete("done"); 849 * completer.complete("done");
822 * foo(); // In this case, foo() runs after bar(). 850 * foo(); // In this case, foo() runs after bar().
823 * }); 851 * });
824 */ 852 */
825 factory Completer.sync() => new _SyncCompleter<T>(); 853 factory Completer.sync() => new _SyncCompleter<T>();
826 854
827 /** The future that will contain the result provided to this completer. */ 855 /** The future completed by this completer. */
floitsch 2017/05/31 15:28:27 It's not always completed yet. maybe? The future
Lasse Reichstein Nielsen 2017/06/02 05:53:38 I think it can work as written. "Completed by" can
828 Future<T> get future; 856 Future<T> get future;
829 857
830 /** 858 /**
831 * Completes [future] with the supplied values. 859 * Completes [future] with the supplied values.
832 * 860 *
833 * The value must be either a value of type [T] 861 * The value must be either a value of type [T]
834 * or a future of type `Future<T>`. 862 * or a future of type `Future<T>`.
835 * 863 *
836 * If the value is itself a future, the completer will wait for that future 864 * If the value is itself a future, the completer will wait for that future
837 * to complete, and complete with the same result, whether it is a success 865 * to complete, and complete with the same result, whether it is a success
838 * or an error. 866 * or an error.
839 * 867 *
840 * Calling `complete` or [completeError] must not be done more than once. 868 * Calling [complete] or [completeError] must be done at most once.
841 * 869 *
842 * All listeners on the future are informed about the value. 870 * All listeners on the future are informed about the value.
843 */ 871 */
844 void complete([FutureOr<T> value]); 872 void complete([FutureOr<T> value]);
845 873
846 /** 874 /**
847 * Complete [future] with an error. 875 * Complete [future] with an error.
848 * 876 *
849 * Calling [complete] or `completeError` must not be done more than once. 877 * Calling [complete] or [completeError] must be done at most once.
850 * 878 *
851 * Completing a future with an error indicates that an exception was thrown 879 * Completing a future with an error indicates that an exception was thrown
852 * while trying to produce a value. 880 * while trying to produce a value.
853 * 881 *
854 * If [error] is `null`, it is replaced by a [NullThrownError]. 882 * If [error] is `null`, it is replaced by a [NullThrownError].
855 * 883 *
856 * If `error` is a `Future`, the future itself is used as the error value. 884 * If `error` is a `Future`, the future itself is used as the error value.
857 * If you want to complete with the result of the future, you can use: 885 * If you want to complete with the result of the future, you can use:
858 * 886 * ```
859 * thisCompleter.complete(theFuture) 887 * thisCompleter.complete(theFuture)
860 * 888 * ```
861 * or if you only want to handle an error from the future: 889 * or if you only want to handle an error from the future:
862 * 890 * ```
863 * theFuture.catchError(thisCompleter.completeError); 891 * theFuture.catchError(thisCompleter.completeError);
864 * 892 * ```
865 */ 893 */
866 void completeError(Object error, [StackTrace stackTrace]); 894 void completeError(Object error, [StackTrace stackTrace]);
867 895
868 /** 896 /**
869 * Whether the future has been completed. 897 * Whether the [future] has been completed.
898 *
899 * Actually reflects whether [complete] or [completeError] has been called.
floitsch 2017/05/31 15:28:27 Remove "Actually".
900 * If [complete] is called with a future, the actual completion my happen
floitsch 2017/05/31 15:28:27 That sounds wrong (and I interpreted it the wrong
Lasse Reichstein Nielsen 2017/06/02 05:53:39 Reworded to something like that. (It doesn't wait
901 * later.
902 *
903 * When this value is `true`, [complete] and [completeError] must not be
904 * called again.
870 */ 905 */
871 bool get isCompleted; 906 bool get isCompleted;
872 } 907 }
873 908
874 // Helper function completing a _Future with error, but checking the zone 909 // Helper function completing a _Future with error, but checking the zone
875 // for error replacement first. 910 // for error replacement first.
876 void _completeWithErrorCallback(_Future result, error, stackTrace) { 911 void _completeWithErrorCallback(_Future result, error, stackTrace) {
877 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); 912 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
878 if (replacement != null) { 913 if (replacement != null) {
879 error = _nonNullError(replacement.error); 914 error = _nonNullError(replacement.error);
880 stackTrace = replacement.stackTrace; 915 stackTrace = replacement.stackTrace;
881 } 916 }
882 result._completeError(error, stackTrace); 917 result._completeError(error, stackTrace);
883 } 918 }
884 919
885 // Like [_completeWIthErrorCallback] but completes asynchronously. 920 // Like [_completeWithErrorCallback] but completes asynchronously.
886 void _asyncCompleteWithErrorCallback(_Future result, error, stackTrace) { 921 void _asyncCompleteWithErrorCallback(_Future result, error, stackTrace) {
887 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); 922 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
888 if (replacement != null) { 923 if (replacement != null) {
889 error = _nonNullError(replacement.error); 924 error = _nonNullError(replacement.error);
890 stackTrace = replacement.stackTrace; 925 stackTrace = replacement.stackTrace;
891 } 926 }
892 result._asyncCompleteError(error, stackTrace); 927 result._asyncCompleteError(error, stackTrace);
893 } 928 }
894 929
895 /** Helper function that converts `null` to a [NullThrownError]. */ 930 /** Helper function that converts `null` to a [NullThrownError]. */
896 Object _nonNullError(Object error) => error ?? new NullThrownError(); 931 Object _nonNullError(Object error) => error ?? new NullThrownError();
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/async/stream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698