OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 import "dart:async"; | 5 import "dart:async"; |
6 | 6 |
7 /// A single-subscription [stream] where the contents are provided later. | 7 /// A single-subscription [stream] where the contents are provided later. |
8 /// | 8 /// |
9 /// It is generally recommended that you never create a `Future<Stream>` | 9 /// It is generally recommended that you never create a `Future<Stream>` |
10 /// because you can just directly create a stream that doesn't do anything | 10 /// because you can just directly create a stream that doesn't do anything |
11 /// until it's ready to do so. | 11 /// until it's ready to do so. |
12 /// This class can be used to create such a stream. | 12 /// This class can be used to create such a stream. |
13 /// | 13 /// |
14 /// The [stream] is a normal stream that you can listen to immediately, | 14 /// The [stream] is a normal stream that you can listen to immediately, |
15 /// but until either [setSourceStream] or [setEmpty] is called, | 15 /// but until either [setSourceStream] or [setEmpty] is called, |
16 /// the stream won't produce any events. | 16 /// the stream won't produce any events. |
17 /// | 17 /// |
18 /// The same effect can be achieved by using a [StreamController] | 18 /// The same effect can be achieved by using a [StreamController] |
19 /// and adding the stream using `addStream` when both | 19 /// and adding the stream using `addStream` when both |
20 /// the controller's stream is listened to and the source stream is ready. | 20 /// the controller's stream is listened to and the source stream is ready. |
21 /// This class attempts to shortcut some of the overhead when possible. | 21 /// This class attempts to shortcut some of the overhead when possible. |
22 /// For example, if the [stream] is only listened to | 22 /// For example, if the [stream] is only listened to |
23 /// after the source stream has been set, | 23 /// after the source stream has been set, |
24 /// the listen is performed directly on the source stream. | 24 /// the listen is performed directly on the source stream. |
25 class StreamCompleter<T> { | 25 class StreamCompleter<T> { |
26 /// The stream doing the actual work, is returned by [stream]. | 26 /// The stream doing the actual work, is returned by [stream]. |
27 final _CompleterStream _stream = new _CompleterStream<T>(); | 27 final _stream = new _CompleterStream<T>(); |
28 | 28 |
29 /// Convert a `Future<Stream>` to a `Stream`. | 29 /// Convert a `Future<Stream>` to a `Stream`. |
30 /// | 30 /// |
31 /// This creates a stream using a stream completer, | 31 /// This creates a stream using a stream completer, |
32 /// and sets the source stream to the result of the future when the | 32 /// and sets the source stream to the result of the future when the |
33 /// future completes. | 33 /// future completes. |
34 /// | 34 /// |
35 /// If the future completes with an error, the returned stream will | 35 /// If the future completes with an error, the returned stream will |
36 /// instead contain just that error. | 36 /// instead contain just that error. |
37 static Stream fromFuture(Future<Stream> streamFuture) { | 37 static Stream/*<T>*/ fromFuture/*<T>*/(Future<Stream/*<T>*/> streamFuture) { |
38 var completer = new StreamCompleter(); | 38 var completer = new StreamCompleter/*<T>*/(); |
39 streamFuture.then(completer.setSourceStream, | 39 streamFuture.then(completer.setSourceStream, |
40 onError: completer.setError); | 40 onError: completer.setError); |
41 return completer.stream; | 41 return completer.stream; |
42 } | 42 } |
43 | 43 |
44 /// The stream of this completer. | 44 /// The stream of this completer. |
45 /// | 45 /// |
46 /// This stream is always a single-subscription stream. | 46 /// This stream is always a single-subscription stream. |
47 /// | 47 /// |
48 /// When a source stream is provided, its events will be forwarded to | 48 /// When a source stream is provided, its events will be forwarded to |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 setSourceStream(new Stream.fromFuture(new Future.error(error, stackTrace))); | 102 setSourceStream(new Stream.fromFuture(new Future.error(error, stackTrace))); |
103 } | 103 } |
104 } | 104 } |
105 | 105 |
106 /// Stream completed by [StreamCompleter]. | 106 /// Stream completed by [StreamCompleter]. |
107 class _CompleterStream<T> extends Stream<T> { | 107 class _CompleterStream<T> extends Stream<T> { |
108 /// Controller for an intermediate stream. | 108 /// Controller for an intermediate stream. |
109 /// | 109 /// |
110 /// Created if the user listens on this stream before the source stream | 110 /// Created if the user listens on this stream before the source stream |
111 /// is set, or if using [_setEmpty] so there is no source stream. | 111 /// is set, or if using [_setEmpty] so there is no source stream. |
112 StreamController _controller; | 112 StreamController<T> _controller; |
113 | 113 |
114 /// Source stream for the events provided by this stream. | 114 /// Source stream for the events provided by this stream. |
115 /// | 115 /// |
116 /// Set when the completer sets the source stream using [_setSourceStream] | 116 /// Set when the completer sets the source stream using [_setSourceStream] |
117 /// or [_setEmpty]. | 117 /// or [_setEmpty]. |
118 Stream _sourceStream; | 118 Stream<T> _sourceStream; |
119 | 119 |
120 StreamSubscription<T> listen(onData(T data), | 120 StreamSubscription<T> listen(onData(T data), |
121 {Function onError, | 121 {Function onError, |
122 void onDone(), | 122 void onDone(), |
123 bool cancelOnError}) { | 123 bool cancelOnError}) { |
124 if (_controller == null) { | 124 if (_controller == null) { |
125 if (_sourceStream != null && !_sourceStream.isBroadcast) { | 125 if (_sourceStream != null && !_sourceStream.isBroadcast) { |
126 // If the source stream is itself single subscription, | 126 // If the source stream is itself single subscription, |
127 // just listen to it directly instead of creating a controller. | 127 // just listen to it directly instead of creating a controller. |
128 return _sourceStream.listen(onData, onError: onError, onDone: onDone, | 128 return _sourceStream.listen(onData, onError: onError, onDone: onDone, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 _sourceStream = _controller.stream; // Mark stream as set. | 177 _sourceStream = _controller.stream; // Mark stream as set. |
178 _controller.close(); | 178 _controller.close(); |
179 } | 179 } |
180 | 180 |
181 // Creates the [_controller]. | 181 // Creates the [_controller]. |
182 void _createController() { | 182 void _createController() { |
183 assert(_controller == null); | 183 assert(_controller == null); |
184 _controller = new StreamController<T>(sync: true); | 184 _controller = new StreamController<T>(sync: true); |
185 } | 185 } |
186 } | 186 } |
OLD | NEW |