Dart: Future, async/await and Streams

How execution is actually ordered, and how to listen for several values over time

⏳ 1. Future and async/await

Actual order of print():

1. Inicio
2. Empieza a pedir datos...
3. Fin de main
4. Datos recibidos

Change how you call obtenerDatos()

void main() {
  print('1. Inicio');
  obtenerDatos();             // <- does NOT wait, continues immediately  print('3. Fin de main');
}
Future obtenerDatos() async {
  print('2. Empieza a pedir datos...');
  await Future.delayed(Duration(seconds: 2));
  print('4. Datos recibidos');
}
💡 Lo importante: await solo pausa esa función

If main() doesn't wait for the Future with await, it keeps running its own lines while obtenerDatos() works in the background. That's why, without await in main, "End of main" comes out BEFORE "Data received".

🌊 2. Streams (several values over time)

Stream Event log of the:

Evento 1: emite 3 → descartado por where()
Evento 2: emite 7 → pasa el filtro, listener imprime 7
Evento 3: emite 1 → descartado por where()
Evento 4: emite 9 → pasa el filtro, listener imprime 9
Evento 5: emite 4 → descartado por where()
Evento 6: emite 12 → pasa el filtro, listener imprime 12

Try your own emissions

final stream = Stream.fromIterable([3, 7, 1, 9, 4, 12]);

stream
    .where((valor) => valor >= 5)
    .listen((valor) => print('Recibido: $valor'));
💡 Future vs Stream

A Future represents a single value that will arrive in the future (or an error). A Stream represents a sequence of values that arrive over time — perfect for keyboard events, socket messages, or results that arrive gradually.

🎯 Key Concepts

Future

  • Represents a future value (or error)
  • await pauses until it's available

async / await

  • Only pauses the function marked async
  • The rest of the program continues

Stream

  • Multiple values over time
  • .listen(), .where(), async*/yield

💪 Practical Exercise

Practice async/await and Streams

  1. Write a function Future<int> sumarAsync(int a, int b) async that returns a + b after a Future.delayed.
  2. Wrap the call to a Future in try/catch to catch a possible error.
  3. Create a stream generator with Stream<int> contarHasta(int n) async* { ... yield i; ... }.

Solution 1

Future sumarAsync(int a, int b) async {
  await Future.delayed(Duration(seconds: 1));
  return a + b;
}

Solution 2

try {
  final resultado = await sumarAsync(2, 3);
  print(resultado);
} catch (e) {
  print('Error: $e');
}

Solution 3

Stream contarHasta(int n) async* {
  for (int i = 1; i <= n; i++) {
    await Future.delayed(Duration(milliseconds: 500));
    yield i;
  }
}