【问题标题】:Can Dart streams save data?Dart 流可以保存数据吗?
【发布时间】:2015-06-01 22:07:49
【问题描述】:

我不清楚 Dart 中的单个订阅者流是否真的保存了他们收到的数据。如果他们这样做了,有没有办法禁用它,因为这似乎是一个重大的内存泄漏?

使用 Dart 中的 new async* 函数,这些产生的流是否存储数据?

【问题讨论】:

    标签: asynchronous stream dart


    【解决方案1】:

    我假设您指的是Future 指的是单个订阅者流

    据我了解,新关键字不会改变实际行为。 async/async* 将分别创建一个Future/Stream,它将自然地缓冲数据,直到它们真正传递。例如,您可以同时执行以下操作:

    import 'dart:async';
    
    Future single() async {
      return 42; 
    }
    
    main() async {
      int r = await single();
      print('ok: $r');
    
      single().then((int val) {
        print('val $val');
      });
    }
    

    所以最后我会说它们的行为相同,你只是用不同的方式表达你正在做的事情。因此,只有在有侦听器的情况下,Stream 才会获取数据。然后数据将像往常一样传送

    来自他们网站的引述:可以使用 Stream 和相关类手动实现流。异步生成器函数是实现此类流的糖

    【讨论】:

    • 其实我说的是async*函数产生的Streams,这些会删除已经传递给订阅者的数据吗?
    • 正如我在帖子中解释的那样,它们与常规的 Stream 对象没有区别,因此它们具有相同的行为。如果没有订阅者,数据将不会被缓冲,如果有,数据将被缓冲,直到交付给所有订阅者,但之后数据不再在流的缓冲区中。如果您不希望这样,请使用 sync Stream(请参阅 StreamController 构造函数并将 sync 设置为 true)。
    【解决方案2】:

    StreamController 构造函数上的代码文档说

    • 控制器将缓冲所有传入事件,直到订阅者停止
    • 已注册。

    为了避免排队事件,您可以使用广播流

    new StreamController.broadcast(...);
    

    或暂停订阅

    StreamSubscription sub;
    sub = s.listen((e) {
      sub.pause();
      // process event
      sub.resume();
    });
    

    async* 创建的流的行为相同

    import 'dart:async';
    
    Stream<int> a() async* {
      for (int i = 1; i <= 10; ++i) {
        print('yield $i');
        yield i;
      }
    }
    
    main() {
    
      a().listen((e) async {
        await new Future.delayed(const Duration(seconds: 1));
        print(e);
      });
    
      StreamSubscription sub;
      sub = a().listen((e) async {
        sub.pause();
        await new Future.delayed(const Duration(seconds: 1));
        print(e);
        sub.resume();
      });
    }
    

    试试DartPad

    第一个例子打印

    yield 1
    yield 2
    yield 3
    yield 4
    yield 5
    yield 6
    yield 7
    yield 8
    yield 9
    yield 10
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    

    第二个例子(带有pause)打印

    yield 1
    yield 2
    yield 3
    1
    2
    yield 4
    3
    yield 5
    4
    yield 6
    5
    yield 7
    6
    yield 8
    7
    yield 9
    8
    yield 10
    9
    10
    

    【讨论】:

    • 澄清一下:async* / yield 是生成广播流还是单个订阅流?
    • 据我所知,一个订阅流,但您可以通过a().isBroadcast查看
    • 非常感谢!我试过:isBroadcastasync* 函数返回false,所以它是一个订阅流。
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 1970-01-01
    • 1970-01-01
    • 2018-02-28
    • 2012-11-11
    相关资源
    最近更新 更多