Chromium Code Reviews| Index: sdk/lib/async/future.dart |
| diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart |
| index 10aa237f9f08d0a8cca20e86d44fcf227ea69874..4bcc36f1bd88253d33487c1e411c110744f5f93e 100644 |
| --- a/sdk/lib/async/future.dart |
| +++ b/sdk/lib/async/future.dart |
| @@ -239,14 +239,22 @@ abstract class Future<T> { |
| * Returns a future which will complete once all the futures in a list are |
| * complete. If any of the futures in the list completes with an error, |
| * the resulting future also completes with an error. Otherwise the value |
| - * of the returned future will be a list of all the values that were produced. |
| + * of the returned future will be a list of all the values that were |
| + * produced. |
| * |
| * If `eagerError` is true, the future completes with an error immediately on |
| * the first error from one of the futures. Otherwise all futures must |
| * complete before the returned future is completed (still with the first |
| * error to occur, the remaining errors are silently dropped). |
| + * |
| + * If [cleanUp] is provided, in the case of an error, any non-null result of |
| + * a successful future is passed to `cleanUp`, which can then release any |
| + * resources that the successful operation allocated. |
| + * The call to `cleanUp` must not throw. |
|
Søren Gjesse
2015/01/09 10:04:11
Please explain what happens if cleanUp actually th
Lasse Reichstein Nielsen
2015/01/09 10:52:09
Done.
|
| */ |
| - static Future<List> wait(Iterable<Future> futures, {bool eagerError: false}) { |
| + static Future<List> wait(Iterable<Future> futures, |
| + {bool eagerError: false, |
| + void cleanUp(successValue)}) { |
| final _Future<List> result = new _Future<List>(); |
| List values; // Collects the values. Set to null on error. |
| int remaining = 0; // How many futures are we waiting for. |
| @@ -254,11 +262,18 @@ abstract class Future<T> { |
| StackTrace stackTrace; // The stackTrace that came with the error. |
| // Handle an error from any of the futures. |
| - handleError(theError, theStackTrace) { |
| - final bool isFirstError = (values != null); |
| - values = null; |
| + void handleError(theError, theStackTrace) { |
| remaining--; |
| - if (isFirstError) { |
| + if (values != null) { |
| + if (cleanUp != null) { |
| + for (var value in values) { |
| + if (value != null) { |
| + // Ensure errors from cleanUp are uncaught. |
| + new Future.sync(() { cleanUp(value); }); |
| + } |
| + } |
| + } |
| + values = null; |
| if (remaining == 0 || eagerError) { |
| result._completeError(theError, theStackTrace); |
| } else { |
| @@ -281,8 +296,14 @@ abstract class Future<T> { |
| if (remaining == 0) { |
| result._completeWithValue(values); |
| } |
| - } else if (remaining == 0 && !eagerError) { |
| - result._completeError(error, stackTrace); |
| + } else { |
| + if (cleanUp != null && value != null) { |
| + // Ensure errors from cleanUp are uncaught. |
| + new Future.sync(() { cleanUp(value); }); |
| + } |
| + if (remaining == 0 && !eagerError) { |
| + result._completeError(error, stackTrace); |
| + } |
| } |
| }, onError: handleError); |
| } |