Reputation: 566
I subscribe to a stream with the listen method so I can process the data as it comes in. If I found what I am looking for, I want to cancel the stream and return the data from the stream subscription block.
I have a working implementation but I am using a Completer to block the function from returning immediate and it feels messy, so I want to know if there's a better way to achieve this. Here is my code snippet:
Future<String> _extractInfo(String url) async {
var data = <int>[];
var client = http.Client();
var request = http.Request('GET', Uri.parse(url));
var response = await client.send(request);
var process = Completer();
var interestingData = '';
StreamSubscription watch;
watch = response.stream.listen((value) async {
data.clear(); //clear the previous stale data from the list so searching can be faster
data.addAll(value);
if (
hasInterestingData(data) //search the bytelist for the data I'm looking for
){
interestingData = extractInterestingData(data) //extract the data if it's been found. This is what I want my function to return;
await watch.cancel(); //cancel the stream subscription if the data has been found. ie: Cancel the download
process.complete('done'); //complete the future, so the function can return interestingData.
}
});
watch.onDone(() {
//complete the future if the data was not found...so the function will return an empty string
if (!process.isCompleted) {
process.complete('done');
}
});
await process.future; //blocks the sync ops below so the function doesn't return immediately
client.close();
return interestingData;
}
Upvotes: 0
Views: 1198
Reputation: 71853
You should use await for
for things like this when you are in an async
function.
Future<String> _extractInfo(String url) async {
var client = http.Client();
var request = http.Request('GET', Uri.parse(url));
var response = await client.send(request);
await for (var data in response.stream) {
if (hasInterestingData(data)) {
return extractInterestingData(data); // Exiting loop cancels the subscription.
}
}
return "done";
}
However, while this approach is equivalent to your code, it's probably equally flawed. Unless you are looking for a single byte, you risk the thing you are looking for being split between consecutive data events. You like do need to retain some part of the previous data array, or some state summarizing what you have already seen, but how much depends on what you are actually looking for.
Upvotes: 2