| 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 /// 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 19 matching lines...) Expand all Loading... |
| 30 /// `Future<int>`. This type union is defined in such a way that | 30 /// `Future<int>`. This type union is defined in such a way that |
| 31 /// `FutureOr<Object>` is both a super- and sub-type of `Object` (sub-type | 31 /// `FutureOr<Object>` is both a super- and sub-type of `Object` (sub-type |
| 32 /// because `Object` is one of the types of the union, super-type because | 32 /// because `Object` is one of the types of the union, super-type because |
| 33 /// `Object` is a super-type of both of the types of the union). Together it | 33 /// `Object` is a super-type of both of the types of the union). Together it |
| 34 /// means that `FutureOr<Object>` is equivalent to `Object`. | 34 /// means that `FutureOr<Object>` is equivalent to `Object`. |
| 35 /// | 35 /// |
| 36 /// As a corollary, `FutureOr<Object>` is equivalent to | 36 /// As a corollary, `FutureOr<Object>` is equivalent to |
| 37 /// `FutureOr<FutureOr<Object>>`, `FutureOr<Future<Object>> is equivalent to | 37 /// `FutureOr<FutureOr<Object>>`, `FutureOr<Future<Object>> is equivalent to |
| 38 /// `Future<Object>`. | 38 /// `Future<Object>`. |
| 39 abstract class FutureOr<T> { | 39 abstract class FutureOr<T> { |
| 40 // Private constructor, so that it is not subclassable, mixable, or | 40 // Private generative constructor, so that it is not subclassable, mixable, or |
| 41 // instantiable. | 41 // instantiable. |
| 42 FutureOr._() { | 42 FutureOr._() { |
| 43 throw new UnsupportedError("FutureOr can't be instantiated"); | 43 throw new UnsupportedError("FutureOr can't be instantiated"); |
| 44 } | 44 } |
| 45 } | 45 } |
| 46 | 46 |
| 47 /** | 47 /** |
| 48 * An object representing a delayed computation. | 48 * An object representing a delayed computation. |
| 49 * | 49 * |
| 50 * A [Future] is used to represent a potential value, or error, | 50 * A [Future] is used to represent a potential value, or error, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 * If the result of executing [computation] throws, the returned future is | 144 * If the result of executing [computation] throws, the returned future is |
| 145 * completed with the error. | 145 * completed with the error. |
| 146 * | 146 * |
| 147 * If the returned value is itself a [Future], completion of | 147 * If the returned value is itself a [Future], completion of |
| 148 * the created future will wait until the returned future completes, | 148 * the created future will wait until the returned future completes, |
| 149 * and will then complete with the same result. | 149 * and will then complete with the same result. |
| 150 * | 150 * |
| 151 * If a non-future value is returned, the returned future is completed | 151 * If a non-future value is returned, the returned future is completed |
| 152 * with that value. | 152 * with that value. |
| 153 */ | 153 */ |
| 154 factory Future(computation()) { | 154 factory Future(FutureOr<T> computation()) { |
| 155 _Future<T> result = new _Future<T>(); | 155 _Future<T> result = new _Future<T>(); |
| 156 Timer.run(() { | 156 Timer.run(() { |
| 157 try { | 157 try { |
| 158 result._complete(computation()); | 158 result._complete(computation()); |
| 159 } catch (e, s) { | 159 } catch (e, s) { |
| 160 _completeWithErrorCallback(result, e, s); | 160 _completeWithErrorCallback(result, e, s); |
| 161 } | 161 } |
| 162 }); | 162 }); |
| 163 return result; | 163 return result; |
| 164 } | 164 } |
| 165 | 165 |
| 166 /** | 166 /** |
| 167 * Creates a future containing the result of calling [computation] | 167 * Creates a future containing the result of calling [computation] |
| 168 * asynchronously with [scheduleMicrotask]. | 168 * asynchronously with [scheduleMicrotask]. |
| 169 * | 169 * |
| 170 * If executing [computation] throws, | 170 * If executing [computation] throws, |
| 171 * the returned future is completed with the thrown error. | 171 * the returned future is completed with the thrown error. |
| 172 * | 172 * |
| 173 * If calling [computation] returns a [Future], completion of | 173 * If calling [computation] returns a [Future], completion of |
| 174 * the created future will wait until the returned future completes, | 174 * the created future will wait until the returned future completes, |
| 175 * and will then complete with the same result. | 175 * and will then complete with the same result. |
| 176 * | 176 * |
| 177 * If calling [computation] returns a non-future value, | 177 * If calling [computation] returns a non-future value, |
| 178 * the returned future is completed with that value. | 178 * the returned future is completed with that value. |
| 179 */ | 179 */ |
| 180 factory Future.microtask(computation()) { | 180 factory Future.microtask(FutureOr<T> computation()) { |
| 181 _Future<T> result = new _Future<T>(); | 181 _Future<T> result = new _Future<T>(); |
| 182 scheduleMicrotask(() { | 182 scheduleMicrotask(() { |
| 183 try { | 183 try { |
| 184 result._complete(computation()); | 184 result._complete(computation()); |
| 185 } catch (e, s) { | 185 } catch (e, s) { |
| 186 _completeWithErrorCallback(result, e, s); | 186 _completeWithErrorCallback(result, e, s); |
| 187 } | 187 } |
| 188 }); | 188 }); |
| 189 return result; | 189 return result; |
| 190 } | 190 } |
| 191 | 191 |
| 192 /** | 192 /** |
| 193 * Creates a future containing the result of immediately calling | 193 * Returns a future containing the result of immediately calling |
| 194 * [computation]. | 194 * [computation]. |
| 195 * | 195 * |
| 196 * If calling [computation] throws, the returned future is completed with the | 196 * If calling [computation] throws, the returned future is completed with the |
| 197 * error. | 197 * error. |
| 198 * | 198 * |
| 199 * If calling [computation] returns a [Future], completion of | 199 * If calling [computation] returns a `Future<T>`, that future is returned. |
| 200 * the created future will wait until the returned future completes, | |
| 201 * and will then complete with the same result. | |
| 202 * | 200 * |
| 203 * If calling [computation] returns a non-future value, | 201 * If calling [computation] returns a non-future value, |
| 204 * the returned future is completed with that value. | 202 * a future is returned which has been completed with that value. |
| 205 */ | 203 */ |
| 206 factory Future.sync(computation()) { | 204 factory Future.sync(FutureOr<T> computation()) { |
| 207 try { | 205 try { |
| 208 var result = computation(); | 206 var result = computation(); |
| 209 return new Future<T>.value(result); | 207 if (result is Future<T>) { |
| 208 return result; |
| 209 } else if (result is Future) { |
| 210 // TODO(lrn): Remove this case for Dart 2.0. |
| 211 return new _Future<T>.immediate(result); |
| 212 } else { |
| 213 return new _Future<T>.value(result); |
| 214 } |
| 210 } catch (error, stackTrace) { | 215 } catch (error, stackTrace) { |
| 211 return new Future<T>.error(error, stackTrace); | 216 var future = new _Future<T>(); |
| 217 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
| 218 if (replacement != null) { |
| 219 future._asyncCompleteError( |
| 220 _nonNullError(replacement.error), replacement.stackTrace); |
| 221 } else { |
| 222 future._asyncCompleteError(error, stackTrace); |
| 223 } |
| 224 return future; |
| 212 } | 225 } |
| 213 } | 226 } |
| 214 | 227 |
| 215 /** | 228 /** |
| 216 * A future whose value is available in the next event-loop iteration. | 229 * A future whose value is available in the next event-loop iteration. |
| 217 * | 230 * |
| 218 * If [value] is not a [Future], using this constructor is equivalent | 231 * If [result] is not a [Future], using this constructor is equivalent |
| 219 * to [:new Future<T>.sync(() => value):]. | 232 * to `new Future<T>.sync(() => result)`. |
| 220 * | 233 * |
| 221 * Use [Completer] to create a Future and complete it later. | 234 * Use [Completer] to create a future and complete it later. |
| 222 */ | 235 */ |
| 223 factory Future.value([value]) { | 236 factory Future.value([FutureOr<T> result]) { |
| 224 return new _Future<T>.immediate(value); | 237 return new _Future<T>.immediate(result); |
| 225 } | 238 } |
| 226 | 239 |
| 227 /** | 240 /** |
| 228 * A future that completes with an error in the next event-loop iteration. | 241 * A future that completes with an error in the next event-loop iteration. |
| 229 * | 242 * |
| 230 * If [error] is `null`, it is replaced by a [NullThrownError]. | 243 * If [error] is `null`, it is replaced by a [NullThrownError]. |
| 231 * | 244 * |
| 232 * Use [Completer] to create a future and complete it later. | 245 * Use [Completer] to create a future and complete it later. |
| 233 */ | 246 */ |
| 234 factory Future.error(Object error, [StackTrace stackTrace]) { | 247 factory Future.error(Object error, [StackTrace stackTrace]) { |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 * Runs [f] for each element in [input] in order, moving to the next element | 428 * Runs [f] for each element in [input] in order, moving to the next element |
| 416 * only when the [Future] returned by [f] completes. Returns a [Future] that | 429 * only when the [Future] returned by [f] completes. Returns a [Future] that |
| 417 * completes when all elements have been processed. | 430 * completes when all elements have been processed. |
| 418 * | 431 * |
| 419 * The return values of all [Future]s are discarded. Any errors will cause the | 432 * The return values of all [Future]s are discarded. Any errors will cause the |
| 420 * iteration to stop and will be piped through the returned [Future]. | 433 * iteration to stop and will be piped through the returned [Future]. |
| 421 * | 434 * |
| 422 * If [f] returns a non-[Future], iteration continues immediately. Otherwise | 435 * If [f] returns a non-[Future], iteration continues immediately. Otherwise |
| 423 * it waits for the returned [Future] to complete. | 436 * it waits for the returned [Future] to complete. |
| 424 */ | 437 */ |
| 425 static Future forEach<T>(Iterable<T> input, dynamic f(T element)) { | 438 static Future forEach<T>(Iterable<T> input, FutureOr f(T element)) { |
| 426 var iterator = input.iterator; | 439 var iterator = input.iterator; |
| 427 return doWhile(() { | 440 return doWhile(() { |
| 428 if (!iterator.moveNext()) return false; | 441 if (!iterator.moveNext()) return false; |
| 429 return new Future.sync(() => f(iterator.current)).then((_) => true); | 442 return new Future.sync(() => f(iterator.current)).then((_) => true); |
| 430 }); | 443 }); |
| 431 } | 444 } |
| 432 | 445 |
| 433 /** | 446 /** |
| 434 * Performs an async operation repeatedly until it returns `false`. | 447 * Performs an async operation repeatedly until it returns `false`. |
| 435 * | 448 * |
| 436 * The function [f] is called repeatedly while it returns either the [bool] | 449 * The function [f] is called repeatedly while it returns either the [bool] |
| 437 * value `true` or a [Future] which completes with the value `true`. | 450 * value `true` or a [Future] which completes with the value `true`. |
| 438 * | 451 * |
| 439 * If a call to [f] returns `false` or a [Future] that completes to `false`, | 452 * If a call to [f] returns `false` or a [Future] that completes to `false`, |
| 440 * iteration ends and the future returned by [doWhile] is completed. | 453 * iteration ends and the future returned by [doWhile] is completed with |
| 454 * a `null` value. |
| 441 * | 455 * |
| 442 * If a future returned by [f] completes with an error, iteration ends and | 456 * If a call to [f] throws or a future returned by [f] completes with |
| 443 * the future returned by [doWhile] completes with the same error. | 457 * an error, iteration ends and the future returned by [doWhile] |
| 444 * | 458 * completes with the same error. |
| 445 * The [f] function must return either a `bool` value or a [Future] completing | |
| 446 * with a `bool` value. | |
| 447 */ | 459 */ |
| 448 static Future doWhile(FutureOr<bool> f()) { | 460 static Future doWhile(FutureOr<bool> f()) { |
| 449 _Future doneSignal = new _Future(); | 461 _Future doneSignal = new _Future(); |
| 450 var nextIteration; | 462 var nextIteration; |
| 451 // Bind this callback explicitly so that each iteration isn't bound in the | 463 // Bind this callback explicitly so that each iteration isn't bound in the |
| 452 // context of all the previous iterations' callbacks. | 464 // context of all the previous iterations' callbacks. |
| 453 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { | 465 nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { |
| 454 if (keepGoing) { | 466 if (keepGoing) { |
| 455 new Future.sync(f) | 467 new Future.sync(f) |
| 456 .then(nextIteration, onError: doneSignal._completeError); | 468 .then(nextIteration, onError: doneSignal._completeError); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 * var f2 = action(); | 614 * var f2 = action(); |
| 603 * if (f2 is Future) return f2.then((_) => v); | 615 * if (f2 is Future) return f2.then((_) => v); |
| 604 * return v | 616 * return v |
| 605 * }, onError: (e) { | 617 * }, onError: (e) { |
| 606 * var f2 = action(); | 618 * var f2 = action(); |
| 607 * if (f2 is Future) return f2.then((_) { throw e; }); | 619 * if (f2 is Future) return f2.then((_) { throw e; }); |
| 608 * throw e; | 620 * throw e; |
| 609 * }); | 621 * }); |
| 610 * } | 622 * } |
| 611 */ | 623 */ |
| 612 Future<T> whenComplete(dynamic action()); | 624 Future<T> whenComplete(FutureOr action()); |
| 613 | 625 |
| 614 /** | 626 /** |
| 615 * Creates a [Stream] containing the result of this future. | 627 * Creates a [Stream] containing the result of this future. |
| 616 * | 628 * |
| 617 * The stream will produce single data or error event containing the | 629 * The stream will produce single data or error event containing the |
| 618 * completion result of this future, and then it will close with a | 630 * completion result of this future, and then it will close with a |
| 619 * done event. | 631 * done event. |
| 620 * | 632 * |
| 621 * If the future never completes, the stream will not produce any events. | 633 * If the future never completes, the stream will not produce any events. |
| 622 */ | 634 */ |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); | 841 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
| 830 if (replacement != null) { | 842 if (replacement != null) { |
| 831 error = _nonNullError(replacement.error); | 843 error = _nonNullError(replacement.error); |
| 832 stackTrace = replacement.stackTrace; | 844 stackTrace = replacement.stackTrace; |
| 833 } | 845 } |
| 834 result._completeError(error, stackTrace); | 846 result._completeError(error, stackTrace); |
| 835 } | 847 } |
| 836 | 848 |
| 837 /** Helper function that converts `null` to a [NullThrownError]. */ | 849 /** Helper function that converts `null` to a [NullThrownError]. */ |
| 838 Object _nonNullError(Object error) => error ?? new NullThrownError(); | 850 Object _nonNullError(Object error) => error ?? new NullThrownError(); |
| OLD | NEW |