Home > Software design >  Flutter Dart Future Function returns before stream.listen
Flutter Dart Future Function returns before stream.listen

Time:09-29

I can't figure this out. I have a future function X that returns a string. I also have a stream.listen async function inside a loop inside the future function X. The problem is, the future function X returns before stream.listen finishes.

Here is the snippet

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

  String? wifiName = "";

  //! Try to get WIFI Name
  wifiName = await _initNetworkInfo();

  //! Ensure we are connected by at least one WIFI
  if (wifiName == "") {
    return Future.error("WIFI not connected!", StackTrace.current);
  }

  //await printIps();
  //! Get local interface and addresses
  List<String>? myInternetAddresses = [];
  for (var interface in await NetworkInterface.list(
    includeLinkLocal: false,
  )) {
    //! Found Interface, now check the address(es) bound to the interface
    print('== Interface: ${interface.name} ==');
    for (var addr in interface.addresses) {

      myInternetAddresses.add(addr.address);
    }
  }

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

  //! Scanner
  // Loop thru the list of IP addresses
  Map<String, String> myHeaders = Map<String, String>();
  //myHeaders['Host'] = 'www.google.com';
  myHeaders['Accept'] = '*/*';
  myHeaders['Accept-Encoding'] = 'gzip, deflate, br';
  myHeaders['Content-type'] = 'application/json';
  myHeaders['Connection'] = 'keep-alive';
  myHeaders['User-Agent'] = "PostmanRuntime/7.29.2";
  //'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.79 Safari/537.36';

  List<dynamic> resultJson = [];
  final int port = 80;
  int countInterface = myInternetAddresses.length;
  int countStream = 0;
  //! Looping thru all the network interfaces including WIFI, Ethernet, etc
  for (String foundIPaddress in myInternetAddresses) {


    //! Get the subnet of the interface IP address, e.g. 10.10.11.x
    String subnet =
        foundIPaddress.substring(0, foundIPaddress.lastIndexOf('.'));
    print("subnet of $subnet");

    //! Create a stream from NetworkAnalyzer
    final stream = NetworkAnalyzer.discover2(subnet, port);

    stream.listen((NetworkAddress addr) async {
      if (addr.exists) {
        //print('Found device: ${addr.ip}');
        //! Ok, now we will call REST API to test

        try {
          print('trying GET REST: ${addr.ip}');
          Map<String, dynamic> jsonResponse;
          myHeaders['Host'] = "google.com";
          //addr.ip.toString();
          Uri myURI = new 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 to decode
            try {
              jsonResponse = json.decode(Uri.decodeFull(response.body));
              if (jsonResponse.isNotEmpty) {
                print('OK');
                //print("jsonResponse: $jsonResponse");
                //! Let's add to the results string
                myClass myCustomClass = new myClass.fromJson(jsonResponse);
                if (myCustomClass.nodeId.isNotEmpty) {
                  myCustomClass.ipaddress = addr.ip.toString();
                  resultJson.add(myCustomClass);
                }
              }
            } catch (e) {
              //! Do nothing
              print("jsondecode error: $e");
            }
          } else {
            print('response.statusCode: ${response.statusCode}');
            //print("Error response.body: ${response.body}");
          }
        } catch (e) {
          // Do nothing
          print("http get error: $e");
        }
      }
    }).onDone(() {
      //
      print("stream.listen DONE: ");

    });
  }


  return resultJson.toString();
  
}

Any tips?

CodePudding user response:

Simply replace your stream.listen with await stream.forEach.

From Stream.forEach docs (emphasis mine):

Executes [action] on each element of this stream. Completes the returned [Future] when all elements of this stream have been processed.

  • Related