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 |