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.