DMarlon Studio

Lección 13 · 13 de 20

Futures, async y await · Dart

Entienda las Future de Dart y escriba código asíncrono legible con async y await, simulando llamadas a un servidor con Future.delayed.

Dart · Futures, async y await en DMarlon Studio: el código del ejemplo y su salida en la terminal

Una `Future<T>` es la promesa de un valor de tipo T que llegará más tarde: la respuesta de un servidor, un archivo leído o el resultado de una consulta. fetchUser y fetchOrders simulan una llamada de red con Future.delayed, que espera unos milisegundos sin bloquear el programa.

Una función marcada como `async` siempre devuelve una Future, aunque dentro haga return de un valor normal: countOrders devuelve Future<int>. Dentro de ella se puede usar `await`, que pausa esa función hasta que la Future termina y entrega su valor.

Fíjese en el orden de la salida. fetchUser(7) arranca la petición y devuelve enseguida una Future pendiente, así que el mensaje 2 se escribe antes de tener el usuario. Solo await pending espera, y entonces aparece el 3. Después, await fetchOrders(...) espera la segunda llamada: con await, el código asíncrono se lee de arriba abajo, como el síncrono, y cada ejecución da la misma salida porque cada paso espera al anterior.

then() es el estilo anterior: registra una función que se ejecuta cuando llega el resultado. Sigue siendo útil, pero async/await es más legible. main también puede ser async y devolver Future<void>. En una aplicación Flutter, los datos de una pantalla se cargan exactamente así, con funciones async que devuelven el modelo ya listo.

Código · main.dart

// Pretend network calls: a Future is a value that arrives later.Future<Map<String, Object>> fetchUser(int id) async {  await Future.delayed(const Duration(milliseconds: 80));  return {'id': id, 'name': 'Elena', 'plan': 'pro'};}Future<List<String>> fetchOrders(int userId) async {  await Future.delayed(const Duration(milliseconds: 40));  return ['#1001 headphones', '#1002 phone case'];}// An async function always returns a Future, even with a plain return.Future<int> countOrders(int userId) async => (await fetchOrders(userId)).length;Future<void> main() async {  print('1. Asking for user 7');  final pending = fetchUser(7); // starts now, does not block  print('2. Main keeps going while the request is in flight');  final user = await pending; // pause here until the value arrives  print('3. Hello, ${user['name']} (${user['plan']} plan)');  // await runs one call after the other, like normal code.  final orders = await fetchOrders(user['id'] as int);  for (final order in orders) {    print('   $order');  }  // The older style: register a callback with then().  await countOrders(7).then((n) => print('4. $n orders in total'));  print('5. Done');}

Salida · dart run main.dart

1. Asking for user 7
2. Main keeps going while the request is in flight
3. Hello, Elena (pro plan)
   #1001 headphones
   #1002 phone case
4. 2 orders in total
5. Done

Para recordar

  • Una Future<T> es un valor que llegará más tarde.
  • Una función async siempre devuelve una Future.
  • await pausa la función hasta tener el valor, sin bloquear el programa.
  • Llamar sin await arranca la tarea y el código sigue adelante.
  • then() es la alternativa con funciones de *callback*.

Ejercicio

Escriba fetchAddress(int userId), que tarde 30 ms y devuelva 'Calle Mayor 5, Madrid', y muestre la dirección entre el saludo y la lista de pedidos.