Home > database >  Flutter how do you return value or error from stream
Flutter how do you return value or error from stream

Time:12-03

I want to use this method, but instead of returning Future<void>, I want to return a value from it. This value is either a final list of bytes or an error (if error happens anytime).

I don't know how to that, since you can't return a value from onDone or onError. If I use await for instead of listen, the errors behave strangely. How to do that?

Future<void> _downloadImage() async {
    _response = await http.Client()
        .send(http.Request('GET', Uri.parse('https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg')));
    _total = _response.contentLength ?? 0;

    _response.stream.listen((value) {
      setState(() {
        _bytes.addAll(value);
        _received  = value.length;
      });
    }).onDone(() async {
      final file = File('${(await getApplicationDocumentsDirectory()).path}/image.png');
      await file.writeAsBytes(_bytes);
      setState(() {
        _image = file;
      });
    });
  }

CodePudding user response:

If you want to return a value from a Future, you can simply use the then method to specify a callback that will be called when the Future completes.

For example, you could modify your _downloadImage method to return the _bytes

list as a Future<List<int>> like this:

Future<List<int>> _downloadImage() async {
  _response = await http.Client()
      .send(http.Request('GET', Uri.parse('https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg')));
  _total = _response.contentLength ?? 0;

  _response.stream.listen((value) {
    setState(() {
      _bytes.addAll(value);
      _received  = value.length;
    });
  }).onDone(() async {
    final file = File('${(await getApplicationDocumentsDirectory()).path}/image.png');
    await file.writeAsBytes(_bytes);
    setState(() {
      _image = file;
    });
  });

  return _bytes;
}

Then you can use the then method to get the value returned by the Future like this:

_downloadImage().then((bytes) {
  // Use the bytes here
});

If you want to handle any errors that may occur while the Future is executing, you can use the catchError method to specify a callback that will be called if an error occurs.

For example, you could modify your _downloadImage method to return a Future<List> that will complete with an error if the HTTP request fails like this:

Future<List<int>> _downloadImage() async {
  try {
    _response = await http.Client()
        .send(http.Request('GET', Uri.parse('https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg')));
    _total = _response.contentLength ?? 0;

    _response.stream.listen((value) {
      setState(() {
        _bytes.addAll(value);
        _received  = value.length;
      });
    }).onDone(() async {
      final file = File('${(await getApplicationDocumentsDirectory()).path}/image.png');
      await file.writeAsBytes(_bytes);
      setState(() {
        _image = file;
      });
    });

    return _bytes;
  } catch (error) {
    return Future.error(error);
  }
}

Then you can use the catchError method to handle any errors that may occur while the Future is executing like this:

_downloadImage().then((bytes) {
  // Use the bytes here
}).catchError((error) {
  // Handle the error here
});

Or you can use the try/catch syntax to handle any errors that may occur while the Future is executing like this:

try {
  _downloadImage().then((bytes) {
    // Use

CodePudding user response:

To return a value from a Future, you can use the then method. The then method takes two arguments: a callback function that will be called when the Future completes successfully, and another callback function that will be called if the Future completes with an error.

Here's an example of how you might update your code to use the then method to return a value from your _downloadImage function:

import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;

Future<List<int>> _downloadImage() async {
  // Send the HTTP request to download the image
  final response = await http.Client()
      .send(http.Request('GET', Uri.parse('https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg')));

  // Get the total size of the image and create an empty list of bytes
  final total = response.contentLength ?? 0;
  final bytes = <int>[];

  // Listen for data events from the response stream and add them to the bytes list
  response.stream.listen((value) {
    bytes.addAll(value);
  });

  // Return a Future that completes with the list of bytes
  return bytes.then((value) {
    // When the Future completes successfully, return the list of bytes
    return value;
  }, one rror: (error) {
    // If the Future completes with an error, return the error
    return error;
  });
}

In this example, the _downloadImage function returns a Future<List> that will contain the list of bytes that were downloaded from the HTTP response stream, or an error if one occurred.

  • Related