Какой тип данных возвращает async-метод в Dart?

Ответ

Async-метод в Dart всегда возвращает объект типа Future<T>, где T — тип результата, который будет вычислен асинхронно. Если метод не возвращает значимого значения, используется Future<void>.

Примеры из реальной практики:

// Возвращает Future<String>
Future<String> fetchUserData(int userId) async {
  final response = await http.get(Uri.parse('https://api.example.com/users/$userId'));
  return response.body; // String
}

// Возвращает Future<List<User>>
Future<List<User>> loadUsersFromDatabase() async {
  final db = await DatabaseHelper.instance.database;
  final maps = await db.query('users');
  return maps.map((map) => User.fromMap(map)).toList();
}

// Возвращает Future<void>
Future<void> saveSettings(Settings settings) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('theme', settings.theme);
  await prefs.setBool('notifications', settings.notificationsEnabled);
}

Ключевые моменты:

  • Ключевое слово async автоматически оборачивает возвращаемое значение в Future
  • Для получения результата Future используется await
  • Исключения внутри async-метода преобразуются в Future, завершившийся с ошибкой, что позволяет обрабатывать их через try/catch с await или через .catchError()

Ответ 18+ 🔞

А, ну ты держись, сейчас я тебе на пальцах объясню, как эта асинхронная магия в Dart работает, а то народ путается, как слепой кот в сортире.

Смотри, главное правило, которое в башку надо вбить: любой метод, который ты пометил async, нихуя не возвращает то, что ты в return написал. Вообще. Он всегда, блядь, всегда возвращает Future<T>. Это как обещание, что результат будет, но не сейчас. T — это как раз то, что ты хочешь вернуть в будущем: String, List<User>, или просто нихуя — void.

Представь, ты заказываешь пиццу. Ты звонишь (async метод), тебе говорят: "Да, конечно, будет ваша пепперони" (Future<Pizza>). Но пиццы у тебя пока нет! Есть только это обещание (Future), что её привезут. await — это когда ты сидишь у двери и ждёшь курьера, не делая ничего другого, пока не получишь заветную коробку (Pizza). Без await ты просто получишь в руки бумажку с номером заказа (Future), а есть будет нечего.

Вот, смотри на живых примерах, чтоб не быть голословным:

// Обещаем, что привезём String (JSON какой-нибудь)
Future<String> fetchUserData(int userId) async {
  // Ждём (await), пока с сервера приедет ответ
  final response = await http.get(Uri.parse('https://api.example.com/users/$userId'));
  // А вот когда приехал, возвращаем уже сам String, но метод-то всё равно Future<String> вернёт!
  return response.body;
}

// Обещаем целый список пользователей. Овердохуища работы!
Future<List<User>> loadUsersFromDatabase() async {
  final db = await DatabaseHelper.instance.database; // Ждём базу
  final maps = await db.query('users'); // Ждём запрос
  // Превращаем сырые данные в нормальные объекты и возвращаем
  return maps.map((map) => User.fromMap(map)).toList();
}

// А тут мы ничего путного не возвращаем, просто делаем дело. Future<void> — это как обещание, что мусор вынесешь.
Future<void> saveSettings(Settings settings) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('theme', settings.theme); // Сделали
  await prefs.setBool('notifications', settings.notificationsEnabled); // Сделали
  // return не нужен, потому что void. Но Future всё равно вернётся!
}

Короче, запомни три вещи, ёпта:

  1. async — это волшебная палочка, которая твой return "привет" превращает в Future<String>. Сам от этого охуеешь сначала.
  2. await — это стоп-кран. Говоришь "авойт" — и всё, поток тупо ждёт, пока этот Future не исполнится, и отдаёт тебе голый результат (String, List). Без него будешь иметь дело с обещанием, а не с данными.
  3. Ошибки — не проблема. Если в асинхронном методе всё пошло по пизде и вылетело исключение, оно не сломает всё приложение нахуй сразу. Оно аккуратно завернётся в тот же Future, но только с ошибкой. Ловить его можно либо старым добрым try/catch вокруг await, либо через .catchError() на самом Future.

Вот и вся философия. Не усложняй. Написал async — готовься получать Future. Хочешь реальные данные — ставь await и не ной.