Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 part of dart.async; | 5 part of dart.async; |
| 6 | 6 |
| 7 // ------------------------------------------------------------------- | 7 // ------------------------------------------------------------------- |
| 8 // Core Stream types | 8 // Core Stream types |
| 9 // ------------------------------------------------------------------- | 9 // ------------------------------------------------------------------- |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 42 * itself when the listener is unsubscribed, even if the stream wasn't done. | 42 * itself when the listener is unsubscribed, even if the stream wasn't done. |
| 43 * | 43 * |
| 44 * Single-subscription streams are generally used for streaming parts of | 44 * Single-subscription streams are generally used for streaming parts of |
| 45 * contiguous data like file I/O. | 45 * contiguous data like file I/O. |
| 46 * | 46 * |
| 47 * A broadcast stream allows any number of listeners, and it fires | 47 * A broadcast stream allows any number of listeners, and it fires |
| 48 * its events when they are ready, whether there are listeners or not. | 48 * its events when they are ready, whether there are listeners or not. |
| 49 * | 49 * |
| 50 * Broadcast streams are used for independent events/observers. | 50 * Broadcast streams are used for independent events/observers. |
| 51 * | 51 * |
| 52 * Stream transformations, such as [where] and [skip], always return | 52 * Stream transformations, such as [where] and [skip], |
| 53 * non-broadcast streams. If several listeners want to listen to the returned | 53 * return the same type of stream as the one the method was called on, |
| 54 * unless otherwise noted. | |
| 55 * | |
| 56 * If several listeners want to listen to the returned | |
| 54 * stream, use [asBroadcastStream] to create a broadcast stream on top of the | 57 * stream, use [asBroadcastStream] to create a broadcast stream on top of the |
| 55 * non-broadcast stream. | 58 * non-broadcast stream. |
| 56 * | 59 * |
| 57 * The default implementation of [isBroadcast] returns false. | 60 * The default implementation of [isBroadcast] returns false. |
| 58 * A broadcast stream inheriting from [Stream] must override [isBroadcast] | 61 * A broadcast stream inheriting from [Stream] must override [isBroadcast] |
| 59 * to return [:true:]. | 62 * to return [:true:]. |
| 60 */ | 63 */ |
| 61 abstract class Stream<T> { | 64 abstract class Stream<T> { |
| 62 Stream(); | 65 Stream(); |
| 63 | 66 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 } | 199 } |
| 197 | 200 |
| 198 /** | 201 /** |
| 199 * Reports whether this stream is a broadcast stream. | 202 * Reports whether this stream is a broadcast stream. |
| 200 */ | 203 */ |
| 201 bool get isBroadcast => false; | 204 bool get isBroadcast => false; |
| 202 | 205 |
| 203 /** | 206 /** |
| 204 * Returns a multi-subscription stream that produces the same events as this. | 207 * Returns a multi-subscription stream that produces the same events as this. |
| 205 * | 208 * |
| 206 * If this stream is already a broadcast stream, it is returned unmodified. | 209 * The returned stream will subscribe to this stream when its first |
| 207 * | |
| 208 * If this stream is single-subscription, return a new stream that allows | |
| 209 * multiple subscribers. It will subscribe to this stream when its first | |
| 210 * subscriber is added, and will stay subscribed until this stream ends, | 210 * subscriber is added, and will stay subscribed until this stream ends, |
| 211 * or a callback cancels the subscription. | 211 * or a callback cancels the subscription. |
| 212 * | 212 * |
| 213 * If [onListen] is provided, it is called with a subscription-like object | 213 * If [onListen] is provided, it is called with a subscription-like object |
| 214 * that represents the underlying subscription to this stream. It is | 214 * that represents the underlying subscription to this stream. It is |
| 215 * possible to pause, resume or cancel the subscription during the call | 215 * possible to pause, resume or cancel the subscription during the call |
| 216 * to [onListen]. It is not possible to change the event handlers, including | 216 * to [onListen]. It is not possible to change the event handlers, including |
| 217 * using [StreamSubscription.asFuture]. | 217 * using [StreamSubscription.asFuture]. |
| 218 * | 218 * |
| 219 * If [onCancel] is provided, it is called in a similar way to [onListen] | 219 * If [onCancel] is provided, it is called in a similar way to [onListen] |
| 220 * when the returned stream stops having listener. If it later gets | 220 * when the returned stream stops having listener. If it later gets |
| 221 * a new listener, the [onListen] function is called again. | 221 * a new listener, the [onListen] function is called again. |
| 222 * | 222 * |
| 223 * Use the callbacks, for example, for pausing the underlying subscription | 223 * Use the callbacks, for example, for pausing the underlying subscription |
| 224 * while having no subscribers to prevent losing events, or canceling the | 224 * while having no subscribers to prevent losing events, or canceling the |
| 225 * subscription when there are no listeners. | 225 * subscription when there are no listeners. |
| 226 */ | 226 */ |
| 227 Stream<T> asBroadcastStream({ | 227 Stream<T> asBroadcastStream({ |
| 228 void onListen(StreamSubscription<T> subscription), | 228 void onListen(StreamSubscription<T> subscription), |
| 229 void onCancel(StreamSubscription<T> subscription) }) { | 229 void onCancel(StreamSubscription<T> subscription) }) { |
| 230 if (isBroadcast) return this; | |
| 231 return new _AsBroadcastStream<T>(this, onListen, onCancel); | 230 return new _AsBroadcastStream<T>(this, onListen, onCancel); |
| 232 } | 231 } |
| 233 | 232 |
| 234 /** | 233 /** |
| 235 * Adds a subscription to this stream. | 234 * Adds a subscription to this stream. |
| 236 * | 235 * |
| 237 * On each data event from this stream, the subscriber's [onData] handler | 236 * On each data event from this stream, the subscriber's [onData] handler |
| 238 * is called. If [onData] is null, nothing happens. | 237 * is called. If [onData] is null, nothing happens. |
| 239 * | 238 * |
| 240 * On errors from this stream, the [onError] handler is given a | 239 * On errors from this stream, the [onError] handler is given a |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 255 { Function onError, | 254 { Function onError, |
| 256 void onDone(), | 255 void onDone(), |
| 257 bool cancelOnError}); | 256 bool cancelOnError}); |
| 258 | 257 |
| 259 /** | 258 /** |
| 260 * Creates a new stream from this stream that discards some data events. | 259 * Creates a new stream from this stream that discards some data events. |
| 261 * | 260 * |
| 262 * The new stream sends the same error and done events as this stream, | 261 * The new stream sends the same error and done events as this stream, |
| 263 * but it only sends the data events that satisfy the [test]. | 262 * but it only sends the data events that satisfy the [test]. |
| 264 * | 263 * |
| 265 * The returned stream is not a broadcast stream, even if this stream is. | 264 * The returned stream is a broadcast stream if this stream is. |
| 266 */ | 265 */ |
| 267 Stream<T> where(bool test(T event)) { | 266 Stream<T> where(bool test(T event)) { |
| 268 return new _WhereStream<T>(this, test); | 267 return new _WhereStream<T>(this, test); |
| 269 } | 268 } |
| 270 | 269 |
| 271 /** | 270 /** |
| 272 * Creates a new stream that converts each element of this stream | 271 * Creates a new stream that converts each element of this stream |
| 273 * to a new value using the [convert] function. | 272 * to a new value using the [convert] function. |
| 274 * | 273 * |
| 275 * The returned stream is not a broadcast stream, even if this stream is. | 274 * The returned stream is a broadcast stream if this stream is. |
| 276 */ | 275 */ |
| 277 Stream map(convert(T event)) { | 276 Stream map(convert(T event)) { |
| 278 return new _MapStream<T, dynamic>(this, convert); | 277 return new _MapStream<T, dynamic>(this, convert); |
| 279 } | 278 } |
| 280 | 279 |
| 281 /** | 280 /** |
| 282 * Creates a new stream with each data event of this stream asynchronously | 281 * Creates a new stream with each data event of this stream asynchronously |
| 283 * mapped to a new event. | 282 * mapped to a new event. |
| 284 * | 283 * |
| 285 * This acts like [map], except that [convert] may return a [Future], | 284 * This acts like [map], except that [convert] may return a [Future], |
| 286 * and in that case, the stream waits for that future to complete before | 285 * and in that case, the stream waits for that future to complete before |
| 287 * continuing with its result. | 286 * continuing with its result. |
| 287 * | |
| 288 * The returned stream is not a broadcast stream. | |
|
nweiz
2014/05/20 21:15:54
Clarify that despite this being a single-subscript
Lasse Reichstein Nielsen
2014/05/21 06:16:53
Technically, streams never buffer anything. Contro
| |
| 288 */ | 289 */ |
| 289 Stream asyncMap(convert(T event)) { | 290 Stream asyncMap(convert(T event)) { |
| 290 StreamController controller; | 291 StreamController controller; |
| 291 StreamSubscription subscription; | 292 StreamSubscription subscription; |
| 292 controller = new StreamController( | 293 controller = new StreamController( |
| 293 onListen: () { | 294 onListen: () { |
| 294 var add = controller.add; | 295 var add = controller.add; |
| 295 var addError = controller.addError; | 296 var addError = controller.addError; |
| 296 subscription = this.listen( | 297 subscription = this.listen( |
| 297 (T event) { | 298 (T event) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 325 /** | 326 /** |
| 326 * Creates a new stream with the events of a stream per original event. | 327 * Creates a new stream with the events of a stream per original event. |
| 327 * | 328 * |
| 328 * This acts like [expand], except that [convert] returns a [Stream] | 329 * This acts like [expand], except that [convert] returns a [Stream] |
| 329 * instead of an [Iterable]. | 330 * instead of an [Iterable]. |
| 330 * The events of the returned stream becomes the events of the returned | 331 * The events of the returned stream becomes the events of the returned |
| 331 * stream, in the order they are produced. | 332 * stream, in the order they are produced. |
| 332 * | 333 * |
| 333 * If [convert] returns `null`, no value is put on the output stream, | 334 * If [convert] returns `null`, no value is put on the output stream, |
| 334 * just as if it returned an empty stream. | 335 * just as if it returned an empty stream. |
| 336 * | |
| 337 * The returned stream is a not a broadcast stream. | |
| 335 */ | 338 */ |
| 336 Stream asyncExpand(Stream convert(T event)) { | 339 Stream asyncExpand(Stream convert(T event)) { |
| 337 StreamController controller; | 340 StreamController controller; |
| 338 StreamSubscription subscription; | 341 StreamSubscription subscription; |
| 339 controller = new StreamController( | 342 controller = new StreamController( |
| 340 onListen: () { | 343 onListen: () { |
| 341 subscription = this.listen( | 344 subscription = this.listen( |
| 342 (T event) { | 345 (T event) { |
| 343 Stream newStream; | 346 Stream newStream; |
| 344 try { | 347 try { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 * returns true. If [test] is omitted, every error is considered matching. | 384 * returns true. If [test] is omitted, every error is considered matching. |
| 382 * | 385 * |
| 383 * If the error is intercepted, the [handle] function can decide what to do | 386 * If the error is intercepted, the [handle] function can decide what to do |
| 384 * with it. It can throw if it wants to raise a new (or the same) error, | 387 * with it. It can throw if it wants to raise a new (or the same) error, |
| 385 * or simply return to make the stream forget the error. | 388 * or simply return to make the stream forget the error. |
| 386 * | 389 * |
| 387 * If you need to transform an error into a data event, use the more generic | 390 * If you need to transform an error into a data event, use the more generic |
| 388 * [Stream.transform] to handle the event by writing a data event to | 391 * [Stream.transform] to handle the event by writing a data event to |
| 389 * the output sink | 392 * the output sink |
| 390 * | 393 * |
| 391 * The returned stream is not a broadcast stream, even if this stream is. | 394 * The returned stream is a broadcast stream if this stream is. |
| 392 */ | 395 */ |
| 393 Stream<T> handleError(Function onError, { bool test(error) }) { | 396 Stream<T> handleError(Function onError, { bool test(error) }) { |
| 394 return new _HandleErrorStream<T>(this, onError, test); | 397 return new _HandleErrorStream<T>(this, onError, test); |
| 395 } | 398 } |
| 396 | 399 |
| 397 /** | 400 /** |
| 398 * Creates a new stream from this stream that converts each element | 401 * Creates a new stream from this stream that converts each element |
| 399 * into zero or more events. | 402 * into zero or more events. |
| 400 * | 403 * |
| 401 * Each incoming event is converted to an [Iterable] of new events, | 404 * Each incoming event is converted to an [Iterable] of new events, |
| 402 * and each of these new events are then sent by the returned stream | 405 * and each of these new events are then sent by the returned stream |
| 403 * in order. | 406 * in order. |
| 404 * | 407 * |
| 405 * The returned stream is not a broadcast stream, even if this stream is. | 408 * The returned stream is a broadcast stream if this stream is. |
| 406 */ | 409 */ |
| 407 Stream expand(Iterable convert(T value)) { | 410 Stream expand(Iterable convert(T value)) { |
| 408 return new _ExpandStream<T, dynamic>(this, convert); | 411 return new _ExpandStream<T, dynamic>(this, convert); |
| 409 } | 412 } |
| 410 | 413 |
| 411 /** | 414 /** |
| 412 * Binds this stream as the input of the provided [StreamConsumer]. | 415 * Binds this stream as the input of the provided [StreamConsumer]. |
| 413 */ | 416 */ |
| 414 Future pipe(StreamConsumer<T> streamConsumer) { | 417 Future pipe(StreamConsumer<T> streamConsumer) { |
| 415 return streamConsumer.addStream(this).then((_) => streamConsumer.close()); | 418 return streamConsumer.addStream(this).then((_) => streamConsumer.close()); |
| 416 } | 419 } |
| 417 | 420 |
| 418 /** | 421 /** |
| 419 * Chains this stream as the input of the provided [StreamTransformer]. | 422 * Chains this stream as the input of the provided [StreamTransformer]. |
| 420 * | 423 * |
| 421 * Returns the result of [:streamTransformer.bind:] itself. | 424 * Returns the result of [:streamTransformer.bind:] itself. |
| 425 * | |
| 426 * The `streamTransformer` can decide whether it wants to return a | |
| 427 * broadcast stream or not. | |
| 422 */ | 428 */ |
| 423 Stream transform(StreamTransformer<T, dynamic> streamTransformer) { | 429 Stream transform(StreamTransformer<T, dynamic> streamTransformer) { |
| 424 return streamTransformer.bind(this); | 430 return streamTransformer.bind(this); |
| 425 } | 431 } |
| 426 | 432 |
| 427 /** | 433 /** |
| 428 * Reduces a sequence of values by repeatedly applying [combine]. | 434 * Reduces a sequence of values by repeatedly applying [combine]. |
| 429 */ | 435 */ |
| 430 Future<T> reduce(T combine(T previous, T element)) { | 436 Future<T> reduce(T combine(T previous, T element)) { |
| 431 _Future<T> result = new _Future<T>(); | 437 _Future<T> result = new _Future<T>(); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 * If this stream produces fewer than [count] values before it's done, | 737 * If this stream produces fewer than [count] values before it's done, |
| 732 * so will the returned stream. | 738 * so will the returned stream. |
| 733 * | 739 * |
| 734 * Stops listening to the stream after the first [n] elements have been | 740 * Stops listening to the stream after the first [n] elements have been |
| 735 * received. | 741 * received. |
| 736 * | 742 * |
| 737 * Internally the method cancels its subscription after these elements. This | 743 * Internally the method cancels its subscription after these elements. This |
| 738 * means that single-subscription (non-broadcast) streams are closed and | 744 * means that single-subscription (non-broadcast) streams are closed and |
| 739 * cannot be reused after a call to this method. | 745 * cannot be reused after a call to this method. |
| 740 * | 746 * |
| 741 * The returned stream is not a broadcast stream, even if this stream is. | 747 * The returned stream is a broadcast stream if this stream is. |
| 742 */ | 748 */ |
| 743 Stream<T> take(int count) { | 749 Stream<T> take(int count) { |
| 744 return new _TakeStream(this, count); | 750 return new _TakeStream(this, count); |
| 745 } | 751 } |
| 746 | 752 |
| 747 /** | 753 /** |
| 748 * Forwards data events while [test] is successful. | 754 * Forwards data events while [test] is successful. |
| 749 * | 755 * |
| 750 * The returned stream provides the same events as this stream as long | 756 * The returned stream provides the same events as this stream as long |
| 751 * as [test] returns [:true:] for the event data. The stream is done | 757 * as [test] returns [:true:] for the event data. The stream is done |
| 752 * when either this stream is done, or when this stream first provides | 758 * when either this stream is done, or when this stream first provides |
| 753 * a value that [test] doesn't accept. | 759 * a value that [test] doesn't accept. |
| 754 * | 760 * |
| 755 * Stops listening to the stream after the accepted elements. | 761 * Stops listening to the stream after the accepted elements. |
| 756 * | 762 * |
| 757 * Internally the method cancels its subscription after these elements. This | 763 * Internally the method cancels its subscription after these elements. This |
| 758 * means that single-subscription (non-broadcast) streams are closed and | 764 * means that single-subscription (non-broadcast) streams are closed and |
| 759 * cannot be reused after a call to this method. | 765 * cannot be reused after a call to this method. |
| 760 * | 766 * |
| 761 * The returned stream is not a broadcast stream, even if this stream is. | 767 * The returned stream is a broadcast stream if this stream is. |
| 762 */ | 768 */ |
| 763 Stream<T> takeWhile(bool test(T element)) { | 769 Stream<T> takeWhile(bool test(T element)) { |
| 764 return new _TakeWhileStream(this, test); | 770 return new _TakeWhileStream(this, test); |
| 765 } | 771 } |
| 766 | 772 |
| 767 /** | 773 /** |
| 768 * Skips the first [count] data events from this stream. | 774 * Skips the first [count] data events from this stream. |
| 769 * | 775 * |
| 770 * The returned stream is not a broadcast stream, even if this stream is. | 776 * The returned stream is a broadcast stream if this stream is. |
| 771 */ | 777 */ |
| 772 Stream<T> skip(int count) { | 778 Stream<T> skip(int count) { |
| 773 return new _SkipStream(this, count); | 779 return new _SkipStream(this, count); |
| 774 } | 780 } |
| 775 | 781 |
| 776 /** | 782 /** |
| 777 * Skip data events from this stream while they are matched by [test]. | 783 * Skip data events from this stream while they are matched by [test]. |
| 778 * | 784 * |
| 779 * Error and done events are provided by the returned stream unmodified. | 785 * Error and done events are provided by the returned stream unmodified. |
| 780 * | 786 * |
| 781 * Starting with the first data event where [test] returns false for the | 787 * Starting with the first data event where [test] returns false for the |
| 782 * event data, the returned stream will have the same events as this stream. | 788 * event data, the returned stream will have the same events as this stream. |
| 783 * | 789 * |
| 784 * The returned stream is not a broadcast stream, even if this stream is. | 790 * The returned stream is a broadcast stream if this stream is. |
| 785 */ | 791 */ |
| 786 Stream<T> skipWhile(bool test(T element)) { | 792 Stream<T> skipWhile(bool test(T element)) { |
| 787 return new _SkipWhileStream(this, test); | 793 return new _SkipWhileStream(this, test); |
| 788 } | 794 } |
| 789 | 795 |
| 790 /** | 796 /** |
| 791 * Skips data events if they are equal to the previous data event. | 797 * Skips data events if they are equal to the previous data event. |
| 792 * | 798 * |
| 793 * The returned stream provides the same events as this stream, except | 799 * The returned stream provides the same events as this stream, except |
| 794 * that it never provides two consequtive data events that are equal. | 800 * that it never provides two consequtive data events that are equal. |
| 795 * | 801 * |
| 796 * Equality is determined by the provided [equals] method. If that is | 802 * Equality is determined by the provided [equals] method. If that is |
| 797 * omitted, the '==' operator on the last provided data element is used. | 803 * omitted, the '==' operator on the last provided data element is used. |
| 798 * | 804 * |
| 799 * The returned stream is not a broadcast stream, even if this stream is. | 805 * The returned stream is a broadcast stream if this stream is. |
| 800 */ | 806 */ |
| 801 Stream<T> distinct([bool equals(T previous, T next)]) { | 807 Stream<T> distinct([bool equals(T previous, T next)]) { |
| 802 return new _DistinctStream(this, equals); | 808 return new _DistinctStream(this, equals); |
| 803 } | 809 } |
| 804 | 810 |
| 805 /** | 811 /** |
| 806 * Returns the first element of the stream. | 812 * Returns the first element of the stream. |
| 807 * | 813 * |
| 808 * Stops listening to the stream after the first element has been received. | 814 * Stops listening to the stream after the first element has been received. |
| 809 * | 815 * |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1081 * The countdown is reset every time an event is forwarded from this stream, | 1087 * The countdown is reset every time an event is forwarded from this stream, |
| 1082 * or when the stream is paused and resumed. | 1088 * or when the stream is paused and resumed. |
| 1083 * | 1089 * |
| 1084 * The [onTimeout] function is called with one argument: an | 1090 * The [onTimeout] function is called with one argument: an |
| 1085 * [EventSink] that allows putting events into the returned stream. | 1091 * [EventSink] that allows putting events into the returned stream. |
| 1086 * This `EventSink` is only valid during the call to `onTimeout`. | 1092 * This `EventSink` is only valid during the call to `onTimeout`. |
| 1087 * | 1093 * |
| 1088 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException] | 1094 * If `onTimeout` is omitted, a timeout will just put a [TimeoutException] |
| 1089 * into the error channel of the returned stream. | 1095 * into the error channel of the returned stream. |
| 1090 * | 1096 * |
| 1091 * The returned stream is not a broadcast stream, even if this stream is. | 1097 * The returned stream is a broadcast stream if this stream is. |
| 1092 */ | 1098 */ |
| 1093 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) { | 1099 Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) { |
| 1100 StreamController controller; | |
| 1101 // The following variables are set on listen. | |
| 1094 StreamSubscription<T> subscription; | 1102 StreamSubscription<T> subscription; |
| 1095 _StreamController controller; | |
| 1096 // The following variables are set on listen. | |
| 1097 Timer timer; | 1103 Timer timer; |
| 1098 Zone zone; | 1104 Zone zone; |
| 1099 Function timeout; | 1105 Function timeout; |
| 1100 | 1106 |
| 1101 void onData(T event) { | 1107 void onData(T event) { |
| 1102 timer.cancel(); | 1108 timer.cancel(); |
| 1103 controller.add(event); | 1109 controller.add(event); |
| 1104 timer = zone.createTimer(timeLimit, timeout); | 1110 timer = zone.createTimer(timeLimit, timeout); |
| 1105 } | 1111 } |
| 1106 void onError(error, StackTrace stackTrace) { | 1112 void onError(error, StackTrace stackTrace) { |
| 1107 timer.cancel(); | 1113 timer.cancel(); |
| 1108 controller.addError(error, stackTrace); | 1114 controller.addError(error, stackTrace); |
| 1109 timer = zone.createTimer(timeLimit, timeout); | 1115 timer = zone.createTimer(timeLimit, timeout); |
| 1110 } | 1116 } |
| 1111 void onDone() { | 1117 void onDone() { |
| 1112 timer.cancel(); | 1118 timer.cancel(); |
| 1113 controller.close(); | 1119 controller.close(); |
| 1114 } | 1120 } |
| 1115 controller = new _SyncStreamController( | 1121 void onListen() { |
| 1116 () { | 1122 // This is the onListen callback for of controller. |
| 1117 // This is the onListen callback for of controller. | 1123 // It runs in the same zone that the subscription was created in. |
| 1118 // It runs in the same zone that the subscription was created in. | 1124 // Use that zone for creating timers and running the onTimeout |
| 1119 // Use that zone for creating timers and running the onTimeout | 1125 // callback. |
| 1120 // callback. | 1126 zone = Zone.current; |
| 1121 zone = Zone.current; | 1127 if (onTimeout == null) { |
| 1122 if (onTimeout == null) { | 1128 timeout = () { |
| 1123 timeout = () { | 1129 controller.addError(new TimeoutException("No stream event", |
| 1124 controller.addError(new TimeoutException("No stream event", | 1130 timeLimit)); |
| 1125 timeLimit)); | 1131 }; |
| 1126 }; | 1132 } else { |
| 1127 } else { | 1133 onTimeout = zone.registerUnaryCallback(onTimeout); |
| 1128 onTimeout = zone.registerUnaryCallback(onTimeout); | 1134 _ControllerEventSinkWrapper wrapper = |
| 1129 _ControllerEventSinkWrapper wrapper = | 1135 new _ControllerEventSinkWrapper(null); |
| 1130 new _ControllerEventSinkWrapper(null); | 1136 timeout = () { |
| 1131 timeout = () { | 1137 wrapper._sink = controller; // Only valid during call. |
| 1132 wrapper._sink = controller; // Only valid during call. | 1138 zone.runUnaryGuarded(onTimeout, wrapper); |
| 1133 zone.runUnaryGuarded(onTimeout, wrapper); | 1139 wrapper._sink = null; |
| 1134 wrapper._sink = null; | 1140 }; |
| 1135 }; | 1141 } |
| 1136 } | |
| 1137 | 1142 |
| 1138 subscription = this.listen(onData, onError: onError, onDone: onDone); | 1143 subscription = this.listen(onData, onError: onError, onDone: onDone); |
| 1139 timer = zone.createTimer(timeLimit, timeout); | 1144 timer = zone.createTimer(timeLimit, timeout); |
| 1140 }, | 1145 } |
| 1141 () { | 1146 Future onCancel() { |
| 1142 timer.cancel(); | 1147 timer.cancel(); |
| 1143 subscription.pause(); | 1148 Future result = subscription.cancel(); |
| 1144 }, | 1149 subscription = null; |
| 1145 () { | 1150 return result; |
| 1146 subscription.resume(); | 1151 } |
| 1147 timer = zone.createTimer(timeLimit, timeout); | 1152 controller = isBroadcast |
| 1148 }, | 1153 ? new _SyncBroadcastStreamController(onListen, onCancel) |
| 1149 () { | 1154 : new _SyncStreamController( |
| 1150 timer.cancel(); | 1155 onListen, |
| 1151 Future result = subscription.cancel(); | 1156 () { |
| 1152 subscription = null; | 1157 // Don't null the timer, onCancel may call cancel again. |
| 1153 return result; | 1158 timer.cancel(); |
| 1154 }); | 1159 subscription.pause(); |
| 1160 }, | |
| 1161 () { | |
| 1162 subscription.resume(); | |
| 1163 timer = zone.createTimer(timeLimit, timeout); | |
| 1164 }, | |
| 1165 onCancel); | |
| 1155 return controller.stream; | 1166 return controller.stream; |
| 1156 } | 1167 } |
| 1157 } | 1168 } |
| 1158 | 1169 |
| 1159 /** | 1170 /** |
| 1160 * A control object for the subscription on a [Stream]. | 1171 * A control object for the subscription on a [Stream]. |
| 1161 * | 1172 * |
| 1162 * When you subscribe on a [Stream] using [Stream.listen], | 1173 * When you subscribe on a [Stream] using [Stream.listen], |
| 1163 * a [StreamSubscription] object is returned. This object | 1174 * a [StreamSubscription] object is returned. This object |
| 1164 * is used to later unsubscribe again, or to temporarily pause | 1175 * is used to later unsubscribe again, or to temporarily pause |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1489 class _ControllerEventSinkWrapper<T> implements EventSink<T> { | 1500 class _ControllerEventSinkWrapper<T> implements EventSink<T> { |
| 1490 EventSink _sink; | 1501 EventSink _sink; |
| 1491 _ControllerEventSinkWrapper(this._sink); | 1502 _ControllerEventSinkWrapper(this._sink); |
| 1492 | 1503 |
| 1493 void add(T data) { _sink.add(data); } | 1504 void add(T data) { _sink.add(data); } |
| 1494 void addError(error, [StackTrace stackTrace]) { | 1505 void addError(error, [StackTrace stackTrace]) { |
| 1495 _sink.addError(error, stackTrace); | 1506 _sink.addError(error, stackTrace); |
| 1496 } | 1507 } |
| 1497 void close() { _sink.close(); } | 1508 void close() { _sink.close(); } |
| 1498 } | 1509 } |
| OLD | NEW |