Index: sdk/lib/async/future.dart |
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart |
index 10aa237f9f08d0a8cca20e86d44fcf227ea69874..7f4050cf8cb6dc661af812fb51bb6f0267b9de57 100644 |
--- a/sdk/lib/async/future.dart |
+++ b/sdk/lib/async/future.dart |
@@ -239,14 +239,24 @@ 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` should not throw. If it does, the error will be an |
+ * uncaught asynchronous error. |
*/ |
- 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 +264,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 +298,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); |
} |