【发布时间】:2015-06-01 22:07:49
【问题描述】:
我不清楚 Dart 中的单个订阅者流是否真的保存了他们收到的数据。如果他们这样做了,有没有办法禁用它,因为这似乎是一个重大的内存泄漏?
使用 Dart 中的 new async* 函数,这些产生的流是否存储数据?
【问题讨论】:
标签: asynchronous stream dart
我不清楚 Dart 中的单个订阅者流是否真的保存了他们收到的数据。如果他们这样做了,有没有办法禁用它,因为这似乎是一个重大的内存泄漏?
使用 Dart 中的 new async* 函数,这些产生的流是否存储数据?
【问题讨论】:
标签: asynchronous stream dart
我假设您指的是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)。
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查看
isBroadcast 为async* 函数返回false,所以它是一个订阅流。