| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.async; | 5 part of dart.async; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * An object representing a delayed computation. | 8 * An object representing a delayed computation. |
| 9 * | 9 * |
| 10 * A [Future] is used to represent a potential value, or error, | 10 * A [Future] is used to represent a potential value, or error, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 * | 110 * |
| 111 * If a non-future value is returned, the returned future is completed | 111 * If a non-future value is returned, the returned future is completed |
| 112 * with that value. | 112 * with that value. |
| 113 */ | 113 */ |
| 114 factory Future(computation()) { | 114 factory Future(computation()) { |
| 115 _Future result = new _Future<T>(); | 115 _Future result = new _Future<T>(); |
| 116 Timer.run(() { | 116 Timer.run(() { |
| 117 try { | 117 try { |
| 118 result._complete(computation()); | 118 result._complete(computation()); |
| 119 } catch (e, s) { | 119 } catch (e, s) { |
| 120 result._completeError(e, s); | 120 _completeWithErrorCallback(result, e, s); |
| 121 } | 121 } |
| 122 }); | 122 }); |
| 123 return result; | 123 return result; |
| 124 } | 124 } |
| 125 | 125 |
| 126 /** | 126 /** |
| 127 * Creates a future containing the result of calling [computation] | 127 * Creates a future containing the result of calling [computation] |
| 128 * asynchronously with [scheduleMicrotask]. | 128 * asynchronously with [scheduleMicrotask]. |
| 129 * | 129 * |
| 130 * If executing [computation] throws, | 130 * If executing [computation] throws, |
| 131 * the returned future is completed with the thrown error. | 131 * the returned future is completed with the thrown error. |
| 132 * | 132 * |
| 133 * If calling [computation] returns a [Future], completion of | 133 * If calling [computation] returns a [Future], completion of |
| 134 * the created future will wait until the returned future completes, | 134 * the created future will wait until the returned future completes, |
| 135 * and will then complete with the same result. | 135 * and will then complete with the same result. |
| 136 * | 136 * |
| 137 * If calling [computation] returns a non-future value, | 137 * If calling [computation] returns a non-future value, |
| 138 * the returned future is completed with that value. | 138 * the returned future is completed with that value. |
| 139 */ | 139 */ |
| 140 factory Future.microtask(computation()) { | 140 factory Future.microtask(computation()) { |
| 141 _Future result = new _Future<T>(); | 141 _Future result = new _Future<T>(); |
| 142 scheduleMicrotask(() { | 142 scheduleMicrotask(() { |
| 143 try { | 143 try { |
| 144 result._complete(computation()); | 144 result._complete(computation()); |
| 145 } catch (e, s) { | 145 } catch (e, s) { |
| 146 result._completeError(e, s); | 146 _completeWithErrorCallback(result, e, s); |
| 147 } | 147 } |
| 148 }); | 148 }); |
| 149 return result; | 149 return result; |
| 150 } | 150 } |
| 151 | 151 |
| 152 /** | 152 /** |
| 153 * Creates a future containing the result of immediately calling | 153 * Creates a future containing the result of immediately calling |
| 154 * [computation]. | 154 * [computation]. |
| 155 * | 155 * |
| 156 * If calling [computation] throws, the returned future is completed with the | 156 * If calling [computation] throws, the returned future is completed with the |
| (...skipping 26 matching lines...) Expand all Loading... |
| 183 factory Future.value([value]) { | 183 factory Future.value([value]) { |
| 184 return new _Future<T>.immediate(value); | 184 return new _Future<T>.immediate(value); |
| 185 } | 185 } |
| 186 | 186 |
| 187 /** | 187 /** |
| 188 * A future that completes with an error in the next event-loop iteration. | 188 * A future that completes with an error in the next event-loop iteration. |
| 189 * | 189 * |
| 190 * Use [Completer] to create a Future and complete it later. | 190 * Use [Completer] to create a Future and complete it later. |
| 191 */ | 191 */ |
| 192 factory Future.error(Object error, [StackTrace stackTrace]) { | 192 factory Future.error(Object error, [StackTrace stackTrace]) { |
| 193 if (!identical(Zone.current, _ROOT_ZONE)) { |
| 194 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
| 195 if (replacement != null) { |
| 196 error = replacement.error; |
| 197 stackTrace = replacement.stackTrace; |
| 198 } |
| 199 } |
| 193 return new _Future<T>.immediateError(error, stackTrace); | 200 return new _Future<T>.immediateError(error, stackTrace); |
| 194 } | 201 } |
| 195 | 202 |
| 196 /** | 203 /** |
| 197 * Creates a future that runs its computation after a delay. | 204 * Creates a future that runs its computation after a delay. |
| 198 * | 205 * |
| 199 * The [computation] will be executed after the given [duration] has passed, | 206 * The [computation] will be executed after the given [duration] has passed, |
| 200 * and the future is completed with the result. | 207 * and the future is completed with the result. |
| 201 * If the duration is 0 or less, | 208 * If the duration is 0 or less, |
| 202 * it completes no sooner than in the next event-loop iteration. | 209 * it completes no sooner than in the next event-loop iteration. |
| 203 * | 210 * |
| 204 * If [computation] is omitted, | 211 * If [computation] is omitted, |
| 205 * it will be treated as if [computation] was set to `() => null`, | 212 * it will be treated as if [computation] was set to `() => null`, |
| 206 * and the future will eventually complete with the `null` value. | 213 * and the future will eventually complete with the `null` value. |
| 207 * | 214 * |
| 208 * If calling [computation] throws, the created future will complete with the | 215 * If calling [computation] throws, the created future will complete with the |
| 209 * error. | 216 * error. |
| 210 * | 217 * |
| 211 * See also [Completer] for a way to create and complete a future at a | 218 * See also [Completer] for a way to create and complete a future at a |
| 212 * later time that isn't necessarily after a known fixed duration. | 219 * later time that isn't necessarily after a known fixed duration. |
| 213 */ | 220 */ |
| 214 factory Future.delayed(Duration duration, [T computation()]) { | 221 factory Future.delayed(Duration duration, [T computation()]) { |
| 215 Completer completer = new Completer.sync(); | 222 _Future result = new _Future<T>(); |
| 216 Future result = completer.future; | 223 new Timer(duration, () { |
| 217 if (computation != null) { | 224 try { |
| 218 result = result.then((ignored) => computation()); | 225 result._complete(computation == null ? null : computation()); |
| 219 } | 226 } catch (e, s) { |
| 220 new Timer(duration, completer.complete); | 227 _completeWithErrorCallback(result, e, s); |
| 228 } |
| 229 }); |
| 221 return result; | 230 return result; |
| 222 } | 231 } |
| 223 | 232 |
| 224 /** | 233 /** |
| 225 * Wait for all the given futures to complete and collect their values. | 234 * Wait for all the given futures to complete and collect their values. |
| 226 * | 235 * |
| 227 * Returns a future which will complete once all the futures in a list are | 236 * Returns a future which will complete once all the futures in a list are |
| 228 * complete. If any of the futures in the list completes with an error, | 237 * complete. If any of the futures in the list completes with an error, |
| 229 * the resulting future also completes with an error. Otherwise the value | 238 * the resulting future also completes with an error. Otherwise the value |
| 230 * of the returned future will be a list of all the values that were produced. | 239 * of the returned future will be a list of all the values that were produced. |
| 231 * | 240 * |
| 232 * If `eagerError` is true, the future completes with an error immediately on | 241 * If `eagerError` is true, the future completes with an error immediately on |
| 233 * the first error from one of the futures. Otherwise all futures must | 242 * the first error from one of the futures. Otherwise all futures must |
| 234 * complete before the returned future is completed (still with the first | 243 * complete before the returned future is completed (still with the first |
| 235 * error to occur, the remaining errors are silently dropped). | 244 * error to occur, the remaining errors are silently dropped). |
| 236 */ | 245 */ |
| 237 static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) { | 246 static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) { |
| 238 Completer completer; // Completer for the returned future. | 247 final _Future<List> result = new _Future<List>(); |
| 239 List values; // Collects the values. Set to null on error. | 248 List values; // Collects the values. Set to null on error. |
| 240 int remaining = 0; // How many futures are we waiting for. | 249 int remaining = 0; // How many futures are we waiting for. |
| 241 var error; // The first error from a future. | 250 var error; // The first error from a future. |
| 242 StackTrace stackTrace; // The stackTrace that came with the error. | 251 StackTrace stackTrace; // The stackTrace that came with the error. |
| 243 | 252 |
| 244 // Handle an error from any of the futures. | 253 // Handle an error from any of the futures. |
| 245 handleError(theError, theStackTrace) { | 254 handleError(theError, theStackTrace) { |
| 246 bool isFirstError = values != null; | 255 final bool isFirstError = (values != null); |
| 247 values = null; | 256 values = null; |
| 248 remaining--; | 257 remaining--; |
| 249 if (isFirstError) { | 258 if (isFirstError) { |
| 250 if (remaining == 0 || eagerError) { | 259 if (remaining == 0 || eagerError) { |
| 251 completer.completeError(theError, theStackTrace); | 260 result._completeError(theError, theStackTrace); |
| 252 } else { | 261 } else { |
| 253 error = theError; | 262 error = theError; |
| 254 stackTrace = theStackTrace; | 263 stackTrace = theStackTrace; |
| 255 } | 264 } |
| 256 } else if (remaining == 0 && !eagerError) { | 265 } else if (remaining == 0 && !eagerError) { |
| 257 completer.completeError(error, stackTrace); | 266 result._completeError(error, stackTrace); |
| 258 } | 267 } |
| 259 } | 268 } |
| 260 | 269 |
| 261 // As each future completes, put its value into the corresponding | 270 // As each future completes, put its value into the corresponding |
| 262 // position in the list of values. | 271 // position in the list of values. |
| 263 for (Future future in futures) { | 272 for (Future future in futures) { |
| 264 int pos = remaining++; | 273 int pos = remaining++; |
| 265 future.then((Object value) { | 274 future.then((Object value) { |
| 266 remaining--; | 275 remaining--; |
| 267 if (values != null) { | 276 if (values != null) { |
| 268 values[pos] = value; | 277 values[pos] = value; |
| 269 if (remaining == 0) { | 278 if (remaining == 0) { |
| 270 completer.complete(values); | 279 result._completeWithValue(values); |
| 271 } | 280 } |
| 272 } else if (remaining == 0 && !eagerError) { | 281 } else if (remaining == 0 && !eagerError) { |
| 273 completer.completeError(error, stackTrace); | 282 result._completeError(error, stackTrace); |
| 274 } | 283 } |
| 275 }, onError: handleError); | 284 }, onError: handleError); |
| 276 } | 285 } |
| 277 if (remaining == 0) { | 286 if (remaining == 0) { |
| 278 return new Future.value(const []); | 287 return new Future.value(const []); |
| 279 } | 288 } |
| 280 values = new List(remaining); | 289 values = new List(remaining); |
| 281 completer = new Completer<List>(); | 290 return result; |
| 282 return completer.future; | |
| 283 } | 291 } |
| 284 | 292 |
| 285 /** | 293 /** |
| 286 * Perform an async operation for each element of the iterable, in turn. | 294 * Perform an async operation for each element of the iterable, in turn. |
| 287 * | 295 * |
| 288 * Runs [f] for each element in [input] in order, moving to the next element | 296 * Runs [f] for each element in [input] in order, moving to the next element |
| 289 * only when the [Future] returned by [f] completes. Returns a [Future] that | 297 * only when the [Future] returned by [f] completes. Returns a [Future] that |
| 290 * completes when all elements have been processed. | 298 * completes when all elements have been processed. |
| 291 * | 299 * |
| 292 * The return values of all [Future]s are discarded. Any errors will cause the | 300 * The return values of all [Future]s are discarded. Any errors will cause the |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 643 * theFuture.catchError(thisCompleter.completeError); | 651 * theFuture.catchError(thisCompleter.completeError); |
| 644 * | 652 * |
| 645 */ | 653 */ |
| 646 void completeError(Object error, [StackTrace stackTrace]); | 654 void completeError(Object error, [StackTrace stackTrace]); |
| 647 | 655 |
| 648 /** | 656 /** |
| 649 * Whether the future has been completed. | 657 * Whether the future has been completed. |
| 650 */ | 658 */ |
| 651 bool get isCompleted; | 659 bool get isCompleted; |
| 652 } | 660 } |
| 661 |
| 662 // Helper function completing a _Future with error, but checking the zone |
| 663 // for error replacement first. |
| 664 void _completeWithErrorCallback(_Future result, error, stackTrace) { |
| 665 AsyncError replacement = Zone.current.errorCallback(error, stackTrace); |
| 666 if (replacement == null) { |
| 667 result._completeError(error, stackTrace); |
| 668 } else { |
| 669 result._completeError(replacement.error, replacement.stackTrace); |
| 670 } |
| 671 } |
| 672 |
| OLD | NEW |