You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何恢复Dart生成器?复用同一生成器无法继续取值求助

问题分析与解决方案

你遇到的问题核心在于async*生成器创建的是冷流,转成广播流后,当所有订阅取消时,源流会被关闭,生成器执行终止。

具体逻辑:

  1. 调用iter()得到单订阅冷流,转成广播流myIter后,第一个await for订阅启动,生成器开始输出0-3,随后break退出循环,订阅取消。
  2. 此时广播流无活跃订阅,触发源流取消操作,生成器停止执行,整个流被关闭。
  3. 第二个await for订阅时,流已处于关闭状态,因此无法进入循环。

解决方案

要复用同一个生成器并获取后续值,需让生成器执行不依赖订阅状态,这里推荐用StreamController手动接管事件分发,确保生成器持续生成值,广播流可随时订阅获取后续事件:

Stream<int> iter() async* {
  for (int i = 0; i < 100; i++) {
    print('generated');
    yield i;
  }
}

void main() async {
  final controller = StreamController<int>();
  
  // 独立启动生成器,持续向controller发送事件
  void runGenerator() async {
    await for (final num in iter()) {
      if (!controller.isClosed) {
        controller.add(num);
      } else {
        break;
      }
    }
    controller.close();
  }
  runGenerator();
  
  // 转成广播流支持多订阅
  final myIter = controller.stream.asBroadcastStream();
  
  int counter = 0;
  await for (var i in myIter) {
    print(i);
    counter++;
    if (counter > 3) break;
  }
  
  counter = 0;
  await Future.delayed(const Duration(seconds: 1));
  
  await for (var i in myIter) {
    print(i);
    counter++;
    if (counter > 3) break;
  }
  
  // 程序结束前关闭controller释放资源
  await controller.close();
}

这段代码的核心逻辑:

  • StreamController作为中间层,接收生成器的所有输出事件
  • 生成器独立运行,不受订阅状态影响,直到生成完所有值或controller被关闭
  • 广播流myIter可被多次订阅,随时获取当前及后续的生成值

运行后会先输出0-3,等待1秒后输出4-7,同时生成器会持续打印generated直到完成100次循环。

内容的提问来源于stack exchange,提问作者Andrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 06:15:29