| 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 obtain a not yet | 10 * A [Future] is used to obtain a not yet |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 return result; | 204 return result; |
| 205 } | 205 } |
| 206 | 206 |
| 207 /** | 207 /** |
| 208 * Wait for all the given futures to complete and collect their values. | 208 * Wait for all the given futures to complete and collect their values. |
| 209 * | 209 * |
| 210 * Returns a future which will complete once all the futures in a list are | 210 * Returns a future which will complete once all the futures in a list are |
| 211 * complete. If any of the futures in the list completes with an error, | 211 * complete. If any of the futures in the list completes with an error, |
| 212 * the resulting future also completes with an error. Otherwise the value | 212 * the resulting future also completes with an error. Otherwise the value |
| 213 * of the returned future will be a list of all the values that were produced. | 213 * of the returned future will be a list of all the values that were produced. |
| 214 * |
| 215 * If `eagerError` is true, the future completes with an error immediately on |
| 216 * the first error from one of the futures. Otherwise all futures must |
| 217 * complete before the returned future is completed (still with the first |
| 218 * error to occur, the remaining errors are silently dropped). |
| 214 */ | 219 */ |
| 215 static Future<List> wait(Iterable<Future> futures) { | 220 static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) { |
| 216 Completer completer; | 221 Completer completer; // Completer for the returned future. |
| 217 // List collecting values from the futures. | 222 List values; // Collects the values. Set to null on error. |
| 218 // Set to null if an error occurs. | 223 int remaining = 0; // How many futures are we waiting for. |
| 219 List values; | 224 var error; // The first error from a future. |
| 225 StackTrace stackTrace; // The stackTrace that came with the error. |
| 220 | 226 |
| 221 dynamic handleError(error, stackTrace) { | 227 // Handle an error from any of the futures. |
| 222 if (values != null) { | 228 handleError(theError, theStackTrace) { |
| 223 values = null; | 229 bool isFirstError = values != null; |
| 230 values = null; |
| 231 remaining--; |
| 232 if (isFirstError) { |
| 233 if (remaining == 0 || eagerError) { |
| 234 completer.completeError(theError, theStackTrace); |
| 235 } else { |
| 236 error = theError; |
| 237 stackTrace = theStackTrace; |
| 238 } |
| 239 } else if (remaining == 0 && !eagerError) { |
| 224 completer.completeError(error, stackTrace); | 240 completer.completeError(error, stackTrace); |
| 225 } | 241 } |
| 226 return null; | |
| 227 } | 242 } |
| 228 | 243 |
| 229 // As each future completes, put its value into the corresponding | 244 // As each future completes, put its value into the corresponding |
| 230 // position in the list of values. | 245 // position in the list of values. |
| 231 int remaining = 0; | |
| 232 for (Future future in futures) { | 246 for (Future future in futures) { |
| 233 int pos = remaining++; | 247 int pos = remaining++; |
| 234 future.catchError(handleError).then((Object value) { | 248 future.then((Object value) { |
| 235 if (values == null) return null; | |
| 236 values[pos] = value; | |
| 237 remaining--; | 249 remaining--; |
| 238 if (remaining == 0) { | 250 if (values != null) { |
| 239 completer.complete(values); | 251 values[pos] = value; |
| 252 if (remaining == 0) { |
| 253 completer.complete(values); |
| 254 } |
| 255 } else if (remaining == 0 && !eagerError) { |
| 256 completer.completeError(error, stackTrace); |
| 240 } | 257 } |
| 241 }); | 258 }, onError: handleError); |
| 242 } | 259 } |
| 243 if (remaining == 0) { | 260 if (remaining == 0) { |
| 244 return new Future.value(const []); | 261 return new Future.value(const []); |
| 245 } | 262 } |
| 246 values = new List(remaining); | 263 values = new List(remaining); |
| 247 completer = new Completer<List>(); | 264 completer = new Completer<List>(); |
| 248 return completer.future; | 265 return completer.future; |
| 249 } | 266 } |
| 250 | 267 |
| 251 /** | 268 /** |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 * theFuture.catchError(thisCompleter.completeError); | 534 * theFuture.catchError(thisCompleter.completeError); |
| 518 * | 535 * |
| 519 */ | 536 */ |
| 520 void completeError(Object error, [StackTrace stackTrace]); | 537 void completeError(Object error, [StackTrace stackTrace]); |
| 521 | 538 |
| 522 /** | 539 /** |
| 523 * Whether the future has been completed. | 540 * Whether the future has been completed. |
| 524 */ | 541 */ |
| 525 bool get isCompleted; | 542 bool get isCompleted; |
| 526 } | 543 } |
| OLD | NEW |