【问题标题】:When does onDone event work for StreamSubscription in Dart?onDone 事件何时对 Dart 中的 StreamSubscription 起作用?
【发布时间】:2020-12-26 06:19:38
【问题描述】:
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

onDone 事件未触发,如果我将sample_stream_1() 程序更改为:

void sample_stream_1() {
  final myGenerator = NumberCreator();
  final myStream = myGenerator.stream;
  myStream
        .take(5)
        .listen(
            (data) => print('Data: $data'),
            onError: (err) => print('Error!'),
            cancelOnError: false,
            onDone: () {
                myGenerator.finish();
                print('Done!');
            },
        );
}

输出是:

[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 事件被触发,但它也会引发异常。

所以:

  1. 为什么 onDone 事件对前一个有效,而对后一个无效?
  2. 为什么我在后一个中会出现异常?
  3. 实现 onDone 事件的正确方法是什么?

【问题讨论】:

    标签: asynchronous dart events stream


    【解决方案1】:
    1. onDone 回调在Stream 关闭时调用。在您提供的第一个示例中,您永远不会关闭 Stream,因此永远不会调用回调。如果您在定时器取消的同时调用关闭函数,它会按您预期的方式工作。 示例:
    Timer.periodic(Duration(seconds: 1), (t) {
      this._controller.sink.add(this._count);
      this._count++;
            if (_count > 10) {
              t.cancel();
              finish();
            }
    });
    
    1. 第二个示例出现异常,因为您正在尝试 将事件添加到您已经关闭的Stream。 5后 取元素完成,您的 onDone 方法被调用,关闭 来自NumberCreatorStream,但Timer 仍在滴答作响,并尝试将事件添加到关闭的Stream。造成混淆的原因可能是 take 方法返回一个 Stream,它在发出提供的事件数(在本例中为 5)后关闭。
    2. 大部分情况下它已经正确完成了,您只是永远不会关闭Stream,因此从不期望它在您认为应该调用的时候被调用。

    【讨论】:

    • 首先,谢谢你的回答,我有一个关于这个问题的问题,但我不能在这里发布,所以请查看下一个帖子(答案),或者我需要将它作为新的发布问题?
    • @ΟυιλιαμΑρκευα 您的问题与您在这里提出的问题没有直接关系。它与最初的要求相差太远了。我建议您在此处接受答案并在通过审核删除之前删除您的答案。
    • 完成,我发了new question
    最近更新 更多