| Index: packages/async/lib/src/stream_completer.dart
|
| diff --git a/packages/async/lib/src/stream_completer.dart b/packages/async/lib/src/stream_completer.dart
|
| index c343e6e7bd2330ccda59e9c793f96b0de3fbed50..4311de5216a7fd0faa10d49e2d0789ba557a1600 100644
|
| --- a/packages/async/lib/src/stream_completer.dart
|
| +++ b/packages/async/lib/src/stream_completer.dart
|
| @@ -2,8 +2,6 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -library async.stream_completer;
|
| -
|
| import "dart:async";
|
|
|
| /// A single-subscription [stream] where the contents are provided later.
|
| @@ -26,7 +24,7 @@ import "dart:async";
|
| /// the listen is performed directly on the source stream.
|
| class StreamCompleter<T> {
|
| /// The stream doing the actual work, is returned by [stream].
|
| - final _CompleterStream _stream = new _CompleterStream<T>();
|
| + final _stream = new _CompleterStream<T>();
|
|
|
| /// Convert a `Future<Stream>` to a `Stream`.
|
| ///
|
| @@ -36,12 +34,9 @@ class StreamCompleter<T> {
|
| ///
|
| /// If the future completes with an error, the returned stream will
|
| /// instead contain just that error.
|
| - static Stream fromFuture(Future<Stream> streamFuture) {
|
| - var completer = new StreamCompleter();
|
| - streamFuture.then(completer.setSourceStream,
|
| - onError: (e, s) {
|
| - completer.setSourceStream(streamFuture.asStream());
|
| - });
|
| + static Stream<T> fromFuture<T>(Future<Stream<T>> streamFuture) {
|
| + var completer = new StreamCompleter<T>();
|
| + streamFuture.then(completer.setSourceStream, onError: completer.setError);
|
| return completer.stream;
|
| }
|
|
|
| @@ -76,8 +71,8 @@ class StreamCompleter<T> {
|
| /// it is immediately listened to, and its events are forwarded to the
|
| /// existing subscription.
|
| ///
|
| - /// Either [setSourceStream] or [setEmpty] may be called at most once.
|
| - /// Trying to call either of them again will fail.
|
| + /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
|
| + /// most once. Trying to call any of them again will fail.
|
| void setSourceStream(Stream<T> sourceStream) {
|
| if (_stream._isSourceStreamSet) {
|
| throw new StateError("Source stream already set");
|
| @@ -87,14 +82,24 @@ class StreamCompleter<T> {
|
|
|
| /// Equivalent to setting an empty stream using [setSourceStream].
|
| ///
|
| - /// Either [setSourceStream] or [setEmpty] may be called at most once.
|
| - /// Trying to call either of them again will fail.
|
| + /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
|
| + /// most once. Trying to call any of them again will fail.
|
| void setEmpty() {
|
| if (_stream._isSourceStreamSet) {
|
| throw new StateError("Source stream already set");
|
| }
|
| _stream._setEmpty();
|
| }
|
| +
|
| + /// Completes this to a stream that emits [error] and then closes.
|
| + ///
|
| + /// This is useful when the process of creating the data for the stream fails.
|
| + ///
|
| + /// Any one of [setSourceStream], [setEmpty], and [setError] may be called at
|
| + /// most once. Trying to call any of them again will fail.
|
| + void setError(error, [StackTrace stackTrace]) {
|
| + setSourceStream(new Stream.fromFuture(new Future.error(error, stackTrace)));
|
| + }
|
| }
|
|
|
| /// Stream completed by [StreamCompleter].
|
| @@ -103,32 +108,30 @@ class _CompleterStream<T> extends Stream<T> {
|
| ///
|
| /// Created if the user listens on this stream before the source stream
|
| /// is set, or if using [_setEmpty] so there is no source stream.
|
| - StreamController _controller;
|
| + StreamController<T> _controller;
|
|
|
| /// Source stream for the events provided by this stream.
|
| ///
|
| /// Set when the completer sets the source stream using [_setSourceStream]
|
| /// or [_setEmpty].
|
| - Stream _sourceStream;
|
| + Stream<T> _sourceStream;
|
|
|
| StreamSubscription<T> listen(onData(T data),
|
| - {Function onError,
|
| - void onDone(),
|
| - bool cancelOnError}) {
|
| + {Function onError, void onDone(), bool cancelOnError}) {
|
| if (_controller == null) {
|
| if (_sourceStream != null && !_sourceStream.isBroadcast) {
|
| // If the source stream is itself single subscription,
|
| // just listen to it directly instead of creating a controller.
|
| - return _sourceStream.listen(onData, onError: onError, onDone: onDone,
|
| - cancelOnError: cancelOnError);
|
| + return _sourceStream.listen(onData,
|
| + onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
| }
|
| _createController();
|
| if (_sourceStream != null) {
|
| _linkStreamToController();
|
| }
|
| }
|
| - return _controller.stream.listen(onData, onError: onError, onDone: onDone,
|
| - cancelOnError: cancelOnError);
|
| + return _controller.stream.listen(onData,
|
| + onError: onError, onDone: onDone, cancelOnError: cancelOnError);
|
| }
|
|
|
| /// Whether a source stream has been set.
|
| @@ -155,8 +158,9 @@ class _CompleterStream<T> extends Stream<T> {
|
| void _linkStreamToController() {
|
| assert(_controller != null);
|
| assert(_sourceStream != null);
|
| - _controller.addStream(_sourceStream, cancelOnError: false)
|
| - .whenComplete(_controller.close);
|
| + _controller
|
| + .addStream(_sourceStream, cancelOnError: false)
|
| + .whenComplete(_controller.close);
|
| }
|
|
|
| /// Sets an empty source stream.
|
| @@ -168,7 +172,7 @@ class _CompleterStream<T> extends Stream<T> {
|
| if (_controller == null) {
|
| _createController();
|
| }
|
| - _sourceStream = _controller.stream; // Mark stream as set.
|
| + _sourceStream = _controller.stream; // Mark stream as set.
|
| _controller.close();
|
| }
|
|
|
|
|