Index: lib/src/result.dart |
diff --git a/lib/src/result.dart b/lib/src/result.dart |
index 49457c35fa113edd7d2ecc629ea5e360b14e9ab4..a4112a9a69a0a8cbe6c484b2cddc7643fe6884ee 100644 |
--- a/lib/src/result.dart |
+++ b/lib/src/result.dart |
@@ -17,6 +17,9 @@ import 'stream_sink_transformer.dart'; |
/// |
/// This value can release itself by writing itself either to a [EventSink] or a |
/// [Completer], or by becoming a [Future]. |
+/// |
+/// A [Future] represents a potential result, one that might not have been |
+/// computed yet, and a [Result] is always a completed and available result. |
abstract class Result<T> { |
/// A stream transformer that captures a stream of events into [Result]s. |
/// |
@@ -55,7 +58,7 @@ abstract class Result<T> { |
/// the call. |
factory Result(T computation()) { |
try { |
- return new ValueResult(computation()); |
+ return new ValueResult<T>(computation()); |
} catch (e, s) { |
return new ErrorResult(e, s); |
} |
@@ -81,6 +84,39 @@ abstract class Result<T> { |
onError: (error, stackTrace) => new ErrorResult<T>(error, stackTrace)); |
} |
+ /// Capture each future in [elements], |
floitsch
2017/08/17 15:29:22
Dartdoc wants third person. Here and for all other
|
+ /// |
+ /// Returns a (future of) a list of results for each element in [elements], |
+ /// in iteration order. |
+ /// Each future in [elements] is [capture]d and each non-future is |
+ /// wrapped as a [Result.value]. |
+ /// The returned future will never have an error. |
+ static Future<List<Result<T>>> captureAll<T>(Iterable<FutureOr<T>> elements) { |
+ var results = <T>[]; |
+ int pending = 0; |
+ var completer; |
+ for (var element in elements) { |
+ if (element is Future<T>) { |
+ int i = results.length; |
+ results.add(null); |
+ pending++; |
+ Result.capture<T>(element).then((result) { |
+ results[i] = result; |
+ if (--pending == 0) { |
+ completer.complete(results); |
+ } |
+ }); |
+ } else { |
+ results.add(new Result<T>.value(element)); |
+ } |
+ } |
+ if (pending == 0) { |
+ return new Future<List<Result<T>>>.value(results); |
+ } |
+ completer = Completer<List<Result<T>>>(); |
+ return completer.future; |
+ } |
+ |
/// Release the result of a captured future. |
/// |
/// Converts the [Result] value of the given [future] to a value or error |
@@ -114,7 +150,22 @@ abstract class Result<T> { |
/// result with the value is returned. |
static Result<T> flatten<T>(Result<Result<T>> result) { |
if (result.isValue) return result.asValue.value; |
- return new ErrorResult<T>(result.asError.error, result.asError.stackTrace); |
+ return result.asError; |
+ } |
+ |
+ /// Converts a sequence of results to a result of a list. |
+ /// |
+ /// Returns either a list of values if [results] doesn't contain any errors, |
+ /// or the first error result in [results]. |
+ static Result<List<T>> flattenList(Iterable<Result<T>> results) { |
+ var values = <T>[]; |
+ for (var result in results) { |
+ if (result.isValue) { |
+ values.add(result.asValue.value); |
+ } |
+ return result.asError; |
+ } |
+ return new Result<List<T>>.value(values); |
} |
/// Whether this result is a value result. |
@@ -135,7 +186,7 @@ abstract class Result<T> { |
/// If this is an error result, return itself. |
/// |
/// Otherwise return `null`. |
- ErrorResult<T> get asError; |
+ ErrorResult get asError; |
/// Complete a completer with this result. |
void complete(Completer<T> completer); |
@@ -145,6 +196,6 @@ abstract class Result<T> { |
/// Calls the sink's `add` or `addError` method as appropriate. |
void addTo(EventSink<T> sink); |
- /// Creates a future completed with this result as a value or an error. |
+ /// A future that has been completed with this result as a value or an error. |
Future<T> get asFuture; |
} |