Search code examples
dartfuturedart-async

Sum of integer values of a Future


I'm trying to parse a HTML document, get all the image-sources and then add the size of all pictures together. Parsing the document works fine, so does getting the image-sources and getting their size.

main(){
  print("Please input an URL");
  var url = stdin.readLineSync();

  getImageUrls(url).then((list) {
    list.forEach((imageUrl) {
      getImageSize(imageUrl).then((r) {
        print("$imageUrl, Size: $r bytes");
      });
    });
  });
}

Future<int> getImageSize(String url){
  final completer = new Completer();
  new StreamController()..stream.listen((str) => completer.complete(imageSize(str)))..add(url);
  return completer.future;
}

imageSize(String url){
  return http.get(url).then((response) => response.bodyBytes.length);
}

I'm struggeling to add the size of each individual image together into one integer. I figured I could do something like this

main(){
  int total = 0;
  print("Please input an URL");
  var url = stdin.readLineSync();

  getImageUrls(url).then((list) {
    list.forEach((imageUrl) {
      getImageSize(imageUrl).then((r) {
        print("$imageUrl, Size: $r bytes");
        total += r;
      });
    });
  });
  print(total);
}

but then I'd need wait for getImageUrls to finish before Im able to print my total.

Can anyone push me in the right direction? I feel like I'm missing something really obvious.


Solution

  • The easiest way is to use the "new" async/await

    main() async {
      int total = 0;
      print("Please input an URL");
      var url = stdin.readLineSync();
    
      var list = await getImageUrls('url');
      for(int i = 0; i < list.length; i++) {
        var imageUrl = list[i];
        var r = await getImageSize(imageUrl);
        print("$imageUrl, Size: $r bytes");
        total += r;
      }
      print(total);
    }
    

    or the Future.wait as mentioned in a comment

    main(){
      int total = 0;
      print("Please input an URL");
      var url = stdin.readLineSync();
    
      getImageUrls(url).then((list) {
        return Future.wait(list.map((r) {
          return getImageSize(imageUrl).then((r) {
            print("$imageUrl, Size: $r bytes");
            total += r;
          });
        });
      }).then((_) => print(total));
    }