Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: lib/result.dart

Issue 1218813011: Add handle method to ErrorResult. (Closed) Base URL: https://github.com/dart-lang/async@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/result_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 5 /// Capture asynchronous results into synchronous values.
6 * Capture asynchronous results into synchronous values, and release them again. 6 ///
7 * 7 /// Capturing a result (either a returned value or a thrown error)
8 * Capturing a result (either a returned value or a thrown error) 8 /// means converting it into a [Result] -
9 * means converting it into a [Result] - 9 /// either a [ValueResult] or an [ErrorResult].
10 * either a [ValueResult] or an [ErrorResult]. 10 ///
11 * 11 /// This value can release itself by writing itself either to a
12 * This value can release itself by writing itself either to a 12 /// [EventSink] or a [Completer], or by becoming a [Future].
13 * [EventSink] or a [Completer], or by becoming a [Future].
14 */
15 library dart.pkg.async.results; 13 library dart.pkg.async.results;
16 14
17 import "dart:async"; 15 import "dart:async";
18 16
19 /** 17 /// The result of a computation.
20 * The result of a computation.
21 */
22 abstract class Result<T> { 18 abstract class Result<T> {
23 /** 19 /// Create a `Result` with the result of calling [computation].
24 * Create a `Result` with the result of calling [computation]. 20 ///
25 * 21 /// This generates either a [ValueResult] with the value returned by
26 * This generates either a [ValueResult] with the value returned by 22 /// calling `computation`, or an [ErrorResult] with an error thrown by
27 * calling `computation`, or an [ErrorResult] with an error thrown by 23 /// the call.
28 * the call.
29 */
30 factory Result(T computation()) { 24 factory Result(T computation()) {
31 try { 25 try {
32 return new ValueResult(computation()); 26 return new ValueResult(computation());
33 } catch (e, s) { 27 } catch (e, s) {
34 return new ErrorResult(e, s); 28 return new ErrorResult(e, s);
35 } 29 }
36 } 30 }
37 31
38 /** 32 /// Create a `Result` holding a value.
39 * Create a `Result` holding a value. 33 ///
40 * 34 /// Alias for [ValueResult.ValueResult].
41 * Alias for [ValueResult.ValueResult].
42 */
43 factory Result.value(T value) = ValueResult<T>; 35 factory Result.value(T value) = ValueResult<T>;
44 36
45 /** 37 /// Create a `Result` holding an error.
46 * Create a `Result` holding an error. 38 ///
47 * 39 /// Alias for [ErrorResult.ErrorResult].
48 * Alias for [ErrorResult.ErrorResult].
49 */
50 factory Result.error(Object error, [StackTrace stackTrace]) => 40 factory Result.error(Object error, [StackTrace stackTrace]) =>
51 new ErrorResult(error, stackTrace); 41 new ErrorResult(error, stackTrace);
52 42
53 // Helper functions. 43 // Helper functions.
54 static _captureValue(value) => new ValueResult(value); 44 static _captureValue(value) => new ValueResult(value);
55 static _captureError(error, stack) => new ErrorResult(error, stack); 45 static _captureError(error, stack) => new ErrorResult(error, stack);
56 static _release(Result v) { 46 static _release(Result v) {
57 if (v.isValue) return v.asValue.value; // Avoid wrapping in future. 47 if (v.isValue) return v.asValue.value; // Avoid wrapping in future.
58 return v.asFuture; 48 return v.asFuture;
59 } 49 }
60 50
61 /** 51 /// Capture the result of a future into a `Result` future.
62 * Capture the result of a future into a `Result` future. 52 ///
63 * 53 /// The resulting future will never have an error.
64 * The resulting future will never have an error. 54 /// Errors have been converted to an [ErrorResult] value.
65 * Errors have been converted to an [ErrorResult] value.
66 */
67 static Future<Result> capture(Future future) { 55 static Future<Result> capture(Future future) {
68 return future.then(_captureValue, onError: _captureError); 56 return future.then(_captureValue, onError: _captureError);
69 } 57 }
70 58
71 /** 59 /// Release the result of a captured future.
72 * Release the result of a captured future. 60 ///
73 * 61 /// Converts the [Result] value of the given [future] to a value or error
74 * Converts the [Result] value of the given [future] to a value or error 62 /// completion of the returned future.
75 * completion of the returned future. 63 ///
76 * 64 /// If [future] completes with an error, the returned future completes with
77 * If [future] completes with an error, the returned future completes with 65 /// the same error.
78 * the same error.
79 */
80 static Future release(Future<Result> future) { 66 static Future release(Future<Result> future) {
81 return future.then(_release); 67 return future.then(_release);
82 } 68 }
83 69
84 /** 70 /// Capture the results of a stream into a stream of [Result] values.
85 * Capture the results of a stream into a stream of [Result] values. 71 ///
86 * 72 /// The returned stream will not have any error events.
87 * The returned stream will not have any error events. 73 /// Errors from the source stream have been converted to [ErrorResult]s.
88 * Errors from the source stream have been converted to [ErrorResult]s. 74 ///
89 * 75 /// Shorthand for transforming the stream using [CaptureStreamTransformer].
90 * Shorthand for transforming the stream using [CaptureStreamTransformer].
91 */
92 static Stream<Result> captureStream(Stream source) { 76 static Stream<Result> captureStream(Stream source) {
93 return source.transform(const CaptureStreamTransformer()); 77 return source.transform(const CaptureStreamTransformer());
94 } 78 }
95 79
96 /** 80 /// Release a stream of [result] values into a stream of the results.
97 * Release a stream of [result] values into a stream of the results. 81 ///
98 * 82 /// `Result` values of the source stream become value or error events in
99 * `Result` values of the source stream become value or error events in 83 /// the returned stream as appropriate.
100 * the returned stream as appropriate. 84 /// Errors from the source stream become errors in the returned stream.
101 * Errors from the source stream become errors in the returned stream. 85 ///
102 * 86 /// Shorthand for transforming the stream using [ReleaseStreamTransformer].
103 * Shorthand for transforming the stream using [ReleaseStreamTransformer].
104 */
105 static Stream releaseStream(Stream<Result> source) { 87 static Stream releaseStream(Stream<Result> source) {
106 return source.transform(const ReleaseStreamTransformer()); 88 return source.transform(const ReleaseStreamTransformer());
107 } 89 }
108 90
109 /** 91 /// Converts a result of a result to a single result.
110 * Converts a result of a result to a single result. 92 ///
111 * 93 /// If the result is an error, or it is a `Result` value
112 * If the result is an error, or it is a `Result` value 94 /// which is then an error, then a result with that error is returned.
113 * which is then an error, then a result with that error is returned. 95 /// Otherwise both levels of results are value results, and a single
114 * Otherwise both levels of results are value results, and a single 96 /// result with the value is returned.
115 * result with the value is returned.
116 */
117 static Result flatten(Result<Result> result) { 97 static Result flatten(Result<Result> result) {
118 if (result.isError) return result; 98 if (result.isError) return result;
119 return result.asValue.value; 99 return result.asValue.value;
120 } 100 }
121 101
122 /** 102 /// Whether this result is a value result.
123 * Whether this result is a value result. 103 ///
124 * 104 /// Always the opposite of [isError].
125 * Always the opposite of [isError].
126 */
127 bool get isValue; 105 bool get isValue;
128 106
129 /** 107 /// Whether this result is an error result.
130 * Whether this result is an error result. 108 ///
131 * 109 /// Always the opposite of [isValue].
132 * Always the opposite of [isValue].
133 */
134 bool get isError; 110 bool get isError;
135 111
136 /** 112 /// If this is a value result, return itself.
137 * If this is a value result, return itself. 113 ///
138 * 114 /// Otherwise return `null`.
139 * Otherwise return `null`.
140 */
141 ValueResult<T> get asValue; 115 ValueResult<T> get asValue;
142 116
143 /** 117 /// If this is an error result, return itself.
144 * If this is an error result, return itself. 118 ///
145 * 119 /// Otherwise return `null`.
146 * Otherwise return `null`.
147 */
148 ErrorResult get asError; 120 ErrorResult get asError;
149 121
150 /** 122 /// Complete a completer with this result.
151 * Complete a completer with this result.
152 */
153 void complete(Completer<T> completer); 123 void complete(Completer<T> completer);
154 124
155 /** 125 /// Add this result to an [EventSink].
156 * Add this result to a [StreamSink]. 126 ///
157 */ 127 /// Calls the sink's `add` or `addError` method as appropriate.
158 void addTo(EventSink<T> sink); 128 void addTo(EventSink<T> sink);
159 129
160 /** 130 /// Creates a future completed with this result as a value or an error.
161 * Creates a future completed with this result as a value or an error.
162 */
163 Future<T> get asFuture; 131 Future<T> get asFuture;
164 } 132 }
165 133
166 /** 134 /// A result representing a returned value.
167 * A result representing a returned value.
168 */
169 class ValueResult<T> implements Result<T> { 135 class ValueResult<T> implements Result<T> {
170 /** The returned value that this result represents. */
171 final T value; 136 final T value;
172 /** Create a value result with the given [value]. */
173 ValueResult(this.value); 137 ValueResult(this.value);
174 bool get isValue => true; 138 bool get isValue => true;
175 bool get isError => false; 139 bool get isError => false;
176 ValueResult<T> get asValue => this; 140 ValueResult<T> get asValue => this;
177 ErrorResult get asError => null; 141 ErrorResult get asError => null;
178 void complete(Completer<T> completer) { 142 void complete(Completer<T> completer) {
179 completer.complete(value); 143 completer.complete(value);
180 } 144 }
181 void addTo(EventSink<T> sink) { 145 void addTo(EventSink<T> sink) {
182 sink.add(value); 146 sink.add(value);
183 } 147 }
184 Future<T> get asFuture => new Future.value(value); 148 Future<T> get asFuture => new Future.value(value);
185 } 149 }
186 150
187 /** 151 /// A result representing a thrown error.
188 * A result representing a thrown error.
189 */
190 class ErrorResult implements Result { 152 class ErrorResult implements Result {
191 /** The thrown object that this result represents. */
192 final error; 153 final error;
193 /** The stack trace, if any, associated with the throw. */
194 final StackTrace stackTrace; 154 final StackTrace stackTrace;
195 /** Create an error result with the given [error] and [stackTrace]. */
196 ErrorResult(this.error, this.stackTrace); 155 ErrorResult(this.error, this.stackTrace);
197 bool get isValue => false; 156 bool get isValue => false;
198 bool get isError => true; 157 bool get isError => true;
199 ValueResult get asValue => null; 158 ValueResult get asValue => null;
200 ErrorResult get asError => this; 159 ErrorResult get asError => this;
201 void complete(Completer completer) { 160 void complete(Completer completer) {
202 completer.completeError(error, stackTrace); 161 completer.completeError(error, stackTrace);
203 } 162 }
204 void addTo(EventSink sink) { 163 void addTo(EventSink sink) {
205 sink.addError(error, stackTrace); 164 sink.addError(error, stackTrace);
206 } 165 }
207 Future get asFuture => new Future.error(error, stackTrace); 166 Future get asFuture => new Future.error(error, stackTrace);
167
168 /// Calls an error handler with the error and stacktrace.
169 ///
170 /// An async error handler function is either a function expecting two
171 /// arguments, which will be called with the error and the stack trace,
172 /// or it has to be a function expecting only one argument,
173 /// which will be called with only the error.
174 void handle(Function errorHandler) {
175 if (errorHandler is ZoneBinaryCallback) {
176 errorHandler(error, stackTrace);
177 } else {
178 errorHandler(error);
179 }
180 }
208 } 181 }
209 182
210 /** 183 /// A stream transformer that captures a stream of events into [Result]s.
211 * A stream transformer that captures a stream of events into [Result]s. 184 ///
212 * 185 /// The result of the transformation is a stream of [Result] values and
213 * The result of the transformation is a stream of [Result] values and 186 /// no error events.
214 * no error events.
215 */
216 class CaptureStreamTransformer<T> implements StreamTransformer<T, Result<T>> { 187 class CaptureStreamTransformer<T> implements StreamTransformer<T, Result<T>> {
217 const CaptureStreamTransformer(); 188 const CaptureStreamTransformer();
218 189
219 Stream<Result<T>> bind(Stream<T> source) { 190 Stream<Result<T>> bind(Stream<T> source) {
220 return new Stream<Result<T>>.eventTransformed(source, _createSink); 191 return new Stream<Result<T>>.eventTransformed(source, _createSink);
221 } 192 }
222 193
223 static EventSink _createSink(EventSink<Result> sink) { 194 static EventSink _createSink(EventSink<Result> sink) {
224 return new CaptureSink(sink); 195 return new CaptureSink(sink);
225 } 196 }
226 } 197 }
227 198
228 /** 199 /// A stream transformer that releases a stream of result events.
229 * A stream transformer that releases a stream of result events. 200 ///
230 * 201 /// The result of the transformation is a stream of values and
231 * The result of the transformation is a stream of values and 202 /// error events.
232 * error events.
233 */
234 class ReleaseStreamTransformer<T> implements StreamTransformer<Result<T>, T> { 203 class ReleaseStreamTransformer<T> implements StreamTransformer<Result<T>, T> {
235 const ReleaseStreamTransformer(); 204 const ReleaseStreamTransformer();
236 205
237 Stream<T> bind(Stream<Result<T>> source) { 206 Stream<T> bind(Stream<Result<T>> source) {
238 return new Stream<T>.eventTransformed(source, _createSink); 207 return new Stream<T>.eventTransformed(source, _createSink);
239 } 208 }
240 209
241 static EventSink<Result> _createSink(EventSink sink) { 210 static EventSink<Result> _createSink(EventSink sink) {
242 return new ReleaseSink(sink); 211 return new ReleaseSink(sink);
243 } 212 }
244 } 213 }
245 214
246 /** 215 /// An event sink wrapper that captures the incoming events.
247 * An event sink wrapper that captures the incoming events. 216 ///
248 * 217 /// Wraps an [EventSink] that expects [Result] values.
249 * Wraps an [EventSink] that expects [Result] values. 218 /// Accepts any value and error result,
250 * Accepts any value and error result, 219 /// and passes them to the wrapped sink as [Result] values.
251 * and passes them to the wrapped sink as [Result] values. 220 ///
252 * 221 /// The wrapped sink will never receive an error event.
253 * The wrapped sink will never receive an error event.
254 */
255 class CaptureSink<T> implements EventSink<T> { 222 class CaptureSink<T> implements EventSink<T> {
256 final EventSink _sink; 223 final EventSink _sink;
257 224
258 CaptureSink(EventSink<Result<T>> sink) : _sink = sink; 225 CaptureSink(EventSink<Result<T>> sink) : _sink = sink;
259 void add(T value) { _sink.add(new ValueResult(value)); } 226 void add(T value) { _sink.add(new ValueResult(value)); }
260 void addError(Object error, [StackTrace stackTrace]) { 227 void addError(Object error, [StackTrace stackTrace]) {
261 _sink.add(new ErrorResult(error, stackTrace)); 228 _sink.add(new ErrorResult(error, stackTrace));
262 } 229 }
263 void close() { _sink.close(); } 230 void close() { _sink.close(); }
264 } 231 }
265 232
266 /** 233 /// An event sink wrapper that releases the incoming result events.
267 * An event sink wrapper that releases the incoming result events. 234 ///
268 * 235 /// Wraps an output [EventSink] that expects any result.
269 * Wraps an output [EventSink] that expects any result. 236 /// Accepts [Result] values, and puts the result value or error into the
270 * Accepts [Result] values, and puts the result value or error into the 237 /// corresponding output sink add method.
271 * corresponding output sink add method.
272 */
273 class ReleaseSink<T> implements EventSink<Result<T>> { 238 class ReleaseSink<T> implements EventSink<Result<T>> {
274 final EventSink _sink; 239 final EventSink _sink;
275 ReleaseSink(EventSink<T> sink) : _sink = sink; 240 ReleaseSink(EventSink<T> sink) : _sink = sink;
276 void add(Result<T> result) { 241 void add(Result<T> result) {
277 if (result.isValue) { 242 if (result.isValue) {
278 _sink.add(result.asValue.value); 243 _sink.add(result.asValue.value);
279 } else { 244 } else {
280 ErrorResult error = result.asError; 245 ErrorResult error = result.asError;
281 _sink.addError(error.error, error.stackTrace); 246 _sink.addError(error.error, error.stackTrace);
282 } 247 }
283 } 248 }
284 void addError(Object error, [StackTrace stackTrace]) { 249 void addError(Object error, [StackTrace stackTrace]) {
285 // Errors may be added by intermediate processing, even if it is never 250 // Errors may be added by intermediate processing, even if it is never
286 // added by CaptureSink. 251 // added by CaptureSink.
287 _sink.addError(error, stackTrace); 252 _sink.addError(error, stackTrace);
288 } 253 }
289 254
290 void close() { _sink.close(); } 255 void close() { _sink.close(); }
291 } 256 }
OLDNEW
« no previous file with comments | « no previous file | test/result_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698