Menu
Coddy logo textTech

Futures y async/await

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 76 de 110.

En las aplicaciones reales, muchas operaciones toman tiempo: obtener datos de un servidor, leer archivos o esperar la entrada del usuario. Dart maneja esto con Future, que representa un valor que estará disponible en algún momento en el futuro.

Un Future es como una promesa: "Te daré el resultado cuando esté listo". Puedes crear uno usando Future.delayed() para simular una operación que toma tiempo:

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Para trabajar con el resultado de un Future, utiliza async y await. Marca tu función como async, luego utiliza await para pausar la ejecución hasta que el Future se complete:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Sin await, obtendrías un Future<String> en lugar de la cadena real. La palabra clave await desenvuelve el Future y te da el valor que contiene. Ten en cuenta que cualquier función que use await debe estar marcada como async, y automáticamente devuelve un Future.

También puedes devolver valores directamente desde funciones async - Dart los envuelve en un Future automáticamente:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Envuelto automáticamente en Future<int>
}
challenge icon

Desafío

Fácil

¡Vamos a crear un servicio meteorológico que simule la obtención de datos climáticos de diferentes ciudades! Practicarás el uso de Future, async y await para manejar operaciones que tardan tiempo en completarse.

Organizarás tu código en dos archivos:

  • weather_service.dart: Crea una clase WeatherService que simule la obtención de información meteorológica. Tu clase debe tener:
    • Un método fetchTemperature(String city) que devuelva un Future<int>. Usa Future.delayed() con una duración de 100 milisegundos para simular el retraso de la red. El método debe devolver una temperatura basada en el nombre de la ciudad: devuelve la longitud del nombre de la ciudad multiplicada por 3.
    • Un método fetchCondition(String city) que devuelva un Future<String>. Usa Future.delayed() con un retraso de 100 milisegundos. Devuelve 'Sunny' si el nombre de la ciudad tiene un número par de caracteres, de lo contrario devuelve 'Cloudy'.
    • Un método asíncrono getFullReport(String city) que devuelva un Future<String>. Este método debe esperar (await) tanto a fetchTemperature como a fetchCondition, y luego devolver una cadena formateada: '[city]: [temperature]C, [condition]'
  • main.dart: Importa tu servicio meteorológico y demuestra cómo funcionan las operaciones asíncronas. Tu función main debe ser asíncrona y:
    • Crear una instancia de WeatherService
    • Imprimir Fetching weather data...
    • Esperar (await) e imprimir el informe completo para 'Paris'
    • Esperar (await) e imprimir el informe completo para 'Tokyo'
    • Esperar (await) e imprimir el informe completo para 'London'
    • Imprimir Done!

Observa cómo cada llamada a getFullReport espera a que se obtengan tanto la temperatura como la condición antes de devolver el resultado combinado. ¡La palabra clave await pausa la ejecución hasta que cada Future se completa!

Salida esperada:

Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!

Hoja de referencia

Un Future representa un valor que estará disponible en el futuro. Se utiliza para operaciones que toman tiempo, como obtener datos o leer archivos.

Crea un Future usando Future.delayed():

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Usa async y await para trabajar con Futures. Marca la función como async y usa await para pausar la ejecución hasta que el Future se complete:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

La palabra clave await desempaqueta el Future y te da el valor real. Sin ella, obtendrías un Future<String> en lugar de la cadena.

Cualquier función que use await debe estar marcada como async y devuelve automáticamente un Future.

Los valores de retorno de las funciones async se envuelven automáticamente en un Future:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Envuelto automáticamente en Future<int>
}

Pruébalo tú mismo

import 'weather_service.dart';

Future<void> main() async {
  // TODO: Crea una instancia de WeatherService
  
  // TODO: Imprime 'Fetching weather data...'
  
  // TODO: Espera e imprime el informe completo para 'Paris'
  
  // TODO: Espera e imprime el informe completo para 'Tokyo'
  
  // TODO: Espera e imprime el informe completo para 'London'
  
  // TODO: Imprime 'Done!'
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos