Flutter. Что такое Future и как его использовать?

В Flutter (и Dart в целом) Future представляет собой потенциальное значение или ошибку, которые станут доступны в будущем. Это, по сути, способ работы Dart с асинхронными операциями, похожий на то, как работают Promises в JavaScript.

Future может находиться в одном из трех состояний:

  1. Не завершён – Асинхронная задача ещё не завершена.
  2. Завершён с результатом – Задача успешно завершена, и доступно значение.
  3. Завершён с ошибкой – Задача завершена с ошибкой.

Как использовать Future

Future часто используется для задач, которые занимают время для выполнения, например:

  • Получение данных из интернета.
  • Чтение или запись в файл.
  • Выполнение сложных вычислений.

Создание Future

Можно создать Future, используя ключевые слова async и await, либо через конструктор Future.

Пример 1: Использование async и await

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));  // Имитируем задержку
  return 'Данные получены!';
}

В этом примере функция fetchData возвращает Future, который завершится с результатом ('Данные получены!') через 2 секунды. Ключевое слово async указывает Dart, что эта функция вернёт Future.

Чтобы использовать эту функцию и получить результат:

void main() async {
  String data = await fetchData();  // Ожидаем завершения Future
  print(data);  // Вывод: Данные получены!
}

Ключевое слово await используется для ожидания завершения Future. Оно приостанавливает выполнение кода до тех пор, пока результат не будет готов.

Пример 2: Использование then() и catchError()

Также можно работать с Future, используя методы then() и catchError(), что удобно, когда нельзя использовать async/await.

void main() {
  fetchData().then((data) {
    print(data);  // Вывод: Данные получены!
  }).catchError((error) {
    print('Произошла ошибка: $error');
  });
}

В этом примере метод then() вызывается, когда Future завершается с результатом, а catchError() используется для обработки возможных ошибок.

Обработка ошибок в Future

При работе с Future необходимо обрабатывать возможные ошибки, которые могут возникнуть во время выполнения асинхронных операций. Ошибки можно обрабатывать с помощью:

  • try / catch с await
  • catchError() с then()

Пример с использованием try / catch:

Future<void> fetchData() async {
  try {
    await Future.delayed(Duration(seconds: 2));
    throw Exception('Ошибка сети');
  } catch (e) {
    print('Ошибка: $e');
  }
}

void main() async {
  await fetchData();  // Вывод: Ошибка: Exception: Ошибка сети
}

Общие сценарии использования Future

  • HTTP-запросы: При получении данных с API, функция http.get() возвращает Future с HTTP-ответом.

    import 'package:http/http.dart' as http;
    
    Future<void> fetchApiData() async {
      var response = await http.get(Uri.parse('https://api.example.com'));
      print(response.body);
    }
    
  • Чтение/запись файлов: Чтение или запись файла возвращает Future, так как эти операции обычно медленные и выполняются асинхронно.
    import 'dart:io';
    
    Future<void> readFile() async {
      var file = File('data.txt');
      String contents = await file.readAsString();
      print(contents);
    }
    

Резюме

  • Future представляет операцию, которая завершится позже с результатом или ошибкой.
  • Вы можете использовать async/await или then()/catchError() для работы с Future.
  • Всегда обрабатывайте возможные ошибки при работе с асинхронным кодом.