Skip to content

dart-stream-async-generator ​

1. 实验目标 ​

用最小 Dart CLI 验证 Stream 与异步生成器(对应 docs/01-runtime-concurrency/13):

  • async* 生成器:yield 逐个产出,消费端逐条收到
  • StreamController:手动控制事件流与关闭(done)
  • 手动背压:StreamSubscription.pause() / resume() 控制消费速率
  • await for:把 Stream 当异步序列循环消费

2. 工程要点 ​

  • 纯 Dart bin/ 入口,不依赖 Flutter UI
  • countDown(n) 用 async* + yield 演示生成器;manualEmitter() 用 StreamController 演示手动推送
  • 背压演示:pause() 后生产者事件排队,resume() 后按顺序继续消费(事件不丢)

3. 关键实现速览 ​

3.1 async* 生成器与消费 ​

为什么看这段:展示"事件逐个产出、消费端逐个收到"的最小模型,也是 Flutter 里 StreamBuilder / RxDart 的底层。

dart
Stream<int> countDown(int n) async* {
  for (var i = n; i >= 1; i--) {
    await Future.delayed(const Duration(milliseconds: 200));
    yield i; // 产出后,消费端 listen 回调立即触发
  }
}

// 消费:await for 相当于 for-in,但每次取下一个事件会 await
await for (final v in countDown(3)) {
  print('countDown 收到: $v');
}

3.2 手动背压 ​

为什么看这段:Dart Stream 默认无背压(事件进队列),pause/resume 是手动节流手段。

dart
final sub = countDown(4).listen((v) => print('[消费端] 收到 $v'));
sub.pause();                       // 暂停消费,事件排队
await Future.delayed(const Duration(seconds: 2));
sub.resume();                      // 恢复,按顺序继续消费

4. 运行方式 ​

bash
cd labs/dart/host
dart run bin/runtime_concurrency/stream_async_generator_demo.dart

5. 预期现象 ​

  • countDown(3):依次打印 3 → 2 → 1(每个间隔 200ms)
  • manualEmitter:每 300ms 一条 event#1..5,最后自动 close
  • 背压段:收到前几条后暂停 2 秒,resume() 后剩余事件按顺序继续(不丢)

6. 常见误区 ​

误区实际情况
Stream 会自动背压不会——事件进缓冲队列;要手动 pause/resume 或自行限速
async* 是立即执行是惰性的:没有 listen 时生成器不会跑(cold stream)
StreamController 用完不关不 close() 会造成监听器永不收到 done,资源悬挂

7. 对应知识库文档 ​

8. 完整源码 ​

站点构建时间:2026/8/24 23:43:17