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

Flutter Dart中Future函数提前于stream.listen返回的问题求助

解决Flutter中Future提前返回Stream未完成的问题

问题根源

scanNetwork4VT函数提前返回的核心原因:循环中调用stream.listen()是异步订阅操作,函数不会等待这些Stream的所有事件处理完成,就直接执行到末尾的return resultJson.toString(),导致Stream内的HTTP请求、JSON解析等逻辑还没执行完,结果就被返回了。

解决方法

方案1:用await for串行处理每个Stream

把stream.listen()替换成await for循环,它会自动遍历Stream的所有事件直到Stream关闭,确保当前子网的所有扫描逻辑完成后,再处理下一个子网:

Future<String> scanNetwork4VT({
  required String commandString,
}) async {
  print("scanNetwork4VT called");

  String wifiName = "";

  // 获取WIFI名称
  wifiName = await _initNetworkInfo();

  // 检查WIFI连接
  if (wifiName == "") {
    return Future.error("WIFI not connected!", StackTrace.current);
  }

  // 获取本地网络接口和地址
  List<String> myInternetAddresses = [];
  for (var interface in await NetworkInterface.list(
    includeLinkLocal: false,
  )) {
    print('== Interface: ${interface.name} ==');
    for (var addr in interface.addresses) {
      myInternetAddresses.add(addr.address);
    }
  }

  if (myInternetAddresses.isEmpty) {
    return Future.error("error", StackTrace.current);
  }

  // 请求头配置
  Map<String, String> myHeaders = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate, br',
    'Content-type': 'application/json',
    'Connection': 'keep-alive',
    'User-Agent': "PostmanRuntime/7.29.2",
  };

  List<dynamic> resultJson = [];
  final int port = 80;

  // 遍历所有网络接口对应的子网
  for (String foundIPaddress in myInternetAddresses) {
    String subnet = foundIPaddress.substring(0, foundIPaddress.lastIndexOf('.'));
    print("subnet of $subnet");

    final stream = NetworkAnalyzer.discover2(subnet, port);

    // 用await for替代listen,等待当前stream所有事件处理完成
    await for (NetworkAddress addr in stream) {
      if (addr.exists) {
        try {
          print('trying GET REST: ${addr.ip}');
          myHeaders['Host'] = "google.com";
          Uri myURI = Uri(
              scheme: "http",
              host: addr.ip.toString(),
              port: 80,
              path: "",
              queryParameters: {"ascdd": ""});

          http.Response response = await http.get(myURI, headers: myHeaders);

          if (response.statusCode == 200) {
            try {
              final jsonResponse = json.decode(Uri.decodeFull(response.body));
              if (jsonResponse.isNotEmpty) {
                print('OK');
                myClass myCustomClass = myClass.fromJson(jsonResponse);
                if (myCustomClass.nodeId.isNotEmpty) {
                  myCustomClass.ipaddress = addr.ip.toString();
                  resultJson.add(myCustomClass);
                }
              }
            } catch (e) {
              print("jsondecode error: $e");
            }
          } else {
            print('response.statusCode: ${response.statusCode}');
          }
        } catch (e) {
          print("http get error: $e");
        }
      }
    }
    print("当前子网扫描完成: $subnet");
  }

  return resultJson.toString();
}

方案2:并行处理所有Stream(提升扫描效率)

如果希望同时扫描所有子网而非逐个串行处理,可以将每个Stream的处理逻辑包装成Future,用Future.wait()等待所有任务完成:

Future<String> scanNetwork4VT({
  required String commandString,
}) async {
  // 前面的WIFI检查、地址获取逻辑和方案1一致

  List<dynamic> resultJson = [];
  final int port = 80;
  // 存储所有子网扫描的Future任务
  List<Future<void>> scanTasks = [];

  for (String foundIPaddress in myInternetAddresses) {
    String subnet = foundIPaddress.substring(0, foundIPaddress.lastIndexOf('.'));
    print("subnet of $subnet");

    final stream = NetworkAnalyzer.discover2(subnet, port);

    // 将当前子网的扫描逻辑包装为Future,加入任务列表
    scanTasks.add(() async {
      await for (NetworkAddress addr in stream) {
        if (addr.exists) {
          // 和方案1相同的HTTP请求、结果处理逻辑
        }
      }
      print("当前子网扫描完成: $subnet");
    }());
  }

  // 等待所有子网的扫描任务完成
  await Future.wait(scanTasks);

  return resultJson.toString();
}

额外优化点

  • 去掉不必要的空安全断言:原代码中myInternetAddresses初始化为空列表,无需用List<String>?和!断言,直接定义为List<String> myInternetAddresses = []即可。
  • 并行方案需注意线程安全:多个任务同时修改resultJson可能存在竞态问题,建议用synchronized包或手动加锁避免数据异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:40:20