如何解决什么时候onDone事件可用于Dart中的StreamSubscription?
void sample_stream_1() {
final myGenerator = NumberCreator();
final myStream = myGenerator.stream;
myStream
.listen(
(data) => print('Data: $data'),onError: (err) => print('Error!'),cancelOnError: false,onDone: () {
myGenerator.finish();
print('Done!');
},);
}
class NumberCreator {
final _controller = StreamController<int>();
var _count = 1;
NumberCreator() {
Timer.periodic(Duration(seconds: 1),(t) {
this._controller.sink.add(this._count);
this._count++;
if (_count > 10) t.cancel();
});
}
Stream<int> get stream => this._controller.stream;
void finish() => this._controller.close();
}
main(List<String> args) {
sample_stream_1();
print('waiting...');
}
输出为:
[Running] dart "./future_stream_demo.dart"
waiting...
Data: 1
Data: 2
Data: 3
Data: 4
Data: 5
Data: 6
Data: 7
Data: 8
Data: 9
Data: 10
[Done] exited with code=0 in 11.164 seconds
如果我将sample_stream_1()
过程更改为此,则不会触发onDone 事件:
void sample_stream_1() {
final myGenerator = NumberCreator();
final myStream = myGenerator.stream;
myStream
.take(5)
.listen(
(data) => print('Data: $data'),);
}
输出为:
[Running] dart "./future_stream_demo.dart"
waiting...
Data: 1
Data: 2
Data: 3
Data: 4
Data: 5
Done!
Unhandled exception:
Bad state: Cannot add event after closing
#0 _StreamController.add (dart:async/stream_controller.dart:623:24)
#1 _StreamSinkWrapper.add (dart:async/stream_controller.dart:900:13)
#2 new NumberCreator.<anonymous closure> (file:./future_stream_demo.dart:275:29)
#3 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:397:19)
#4 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
[Done] exited with code=255 in 6.298 seconds
会触发onDone 事件,但也会引发异常。
所以:
- 为什么onDone事件适用于前一个而不适用于后一个?
- 为什么我要在后者中获得例外?
- 实现onDone事件的正确方法是什么?
解决方法
- 关闭
onDone
时将调用Stream
回调。在您提供的第一个示例中,您永远不会关闭Stream
,因此永远不会调用该回调。如果您在取消计时器的同时调用关闭函数,它将以您期望的方式工作。 示例:
Timer.periodic(Duration(seconds: 1),(t) {
this._controller.sink.add(this._count);
this._count++;
if (_count > 10) {
t.cancel();
finish();
}
});
- 在第二个示例中出现异常,因为您正在尝试
向已关闭的
Stream
添加事件。 5之后 元素完成后,您的onDone
方法被调用,关闭Stream
中的NumberCreator
,但Timer
仍在滴答中,并尝试向关闭的Stream
添加事件。造成这种混淆的原因可能是,take
方法返回一个Stream
,该方法在发出所提供的事件数(在本例中为5)后关闭。 - 在大多数情况下,它已经正确地完成了,您永远不会关闭
Stream
,因此,在您认为应该调用它的时候就永远不会期望它被调用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。