Ответ
В Dart Future представляет отложенное вычисление или асинхронную операцию. Я создаю их несколькими способами в зависимости от задачи.
1. Использование конструкторов класса Future
Это низкоуровневые конструкторы для ручного создания Future.
-
Future(): Обертывает синхронную или асинхронную операцию, выполняемую в event loop.Future<int> heavyCalculation() { return Future(() { // Имитация долгой синхронной операции int result = 0; for (int i = 0; i < 1000000000; i++) { result += i; } return result; // Будет обернуто в завершенный Future }); } -
Future.delayed(): Создает Future, который завершается с результатом функции после задержки. Часто используется для имитации сетевых запросов или таймеров.Future<String> fetchUserData() { return Future.delayed( const Duration(seconds: 2), () => '{"name": "John"}', // Эта функция выполнится через 2 секунды ); } -
Future.value(): Немедленно создает завершенный успешный Future с заданным значением. Полезно в тестах или для возврата кэшированных данных.Future<Config> loadConfig() { if (_cachedConfig != null) { return Future.value(_cachedConfig!); // Немедленный возврат } return _fetchFromNetwork(); } -
Future.error(): Немедленно создает завершенный Future с ошибкой.Future<void> validateLogin(String email) { if (!email.contains('@')) { return Future.error(FormatException('Invalid email')); } return _checkServer(); }
2. Использование async/await
Любая функция, помеченная ключевым словом async, автоматически возвращает Future. Это самый частый способ в production-коде.
Future<List<Post>> fetchPosts() async {
// `await` приостанавливает выполнение функции, но не потока.
final response = await http.get(Uri.parse('https://api.example.com/posts'));
if (response.statusCode == 200) {
return (jsonDecode(response.body) as List).map((e) => Post.fromJson(e)).toList();
} else {
throw Exception('Failed to load posts');
}
}
// Функция fetchPosts возвращает Future<List<Post>>
3. Преобразование Stream в Future
Методы first, last, single, elementAt и reduce у Stream возвращают Future.
Future<int> getFirstValueFromStream(Stream<int> stream) {
return stream.first; // Возвращает Future<int>
}
Выбор способа: Для работы с внешними ресурсами (сеть, БД) я использую async-функции. Для создания отложенных задач или моков в тестах — конструкторы Future.delayed или Future.value.