Librería dart:async

La librería dart:async proporciona las funcionalidades esenciales para la programación asíncrona en Dart: Future y Stream.

  1. No siempre es necesario importar manualmente dart:async para usar Future / Stream, ya que dart:core ya lo exporta;
  2. Si necesitas utilizar tipos como StreamController, StreamSubscription o ParallelWaitError, debes realizar la importación explícita:
import 'dart:async';Lenguaje del código: JavaScript (javascript)

Dos conceptos fundamentales:

  • Future: Representa un resultado asíncrono único (solo generará un valor o un error en algún momento futuro)
  • Stream: Representa una secuencia continua de datos asíncronos (produce múltiples valores de forma sucesiva, similar a un flujo de eventos)

Future

1. async / await

Se recomienda prioritariamente, mejora la legibilidad frente a las cadenas de llamadas .then()

  • Las funciones marcadas con async devuelven un Future;
  • await espera a que el Future finalice, pausando la ejecución hasta obtener el resultado;
  • Emplea try-catch para capturar excepciones asíncronas.
// Las funciones async retornan Future
Future<String> findEntryPoint() async => "main.dart";
Future<int> runExecutable(String entry, List args) async => 0;
Future<void> flushThenExit(int code) async {}

// Sintaxis con await (recomendada)
Future<void> runUsingAsyncAwait() async {
  try {
    var entryPoint = await findEntryPoint();
    var exitCode = await runExecutable(entryPoint, []);
    await flushThenExit(exitCode);
  } catch (e) {
    // Captura general de errores
    print("Ocurrió un error: $e");
  }
}Lenguaje del código: JavaScript (javascript)

2. Sintaxis encadenada tradicional .then() / .catchError()

  • .then(): Ejecuta una función de retorno cuando el Future se completa con éxito; devuelve un nuevo Future para seguir encadenando operaciones
  • .catchError(): Captura excepciones; debe encadenarse al resultado devuelto por then, si no no podrá interceptar errores generados dentro de then
void runUsingFuture() {
  findEntryPoint()
      .then((entryPoint) {
        return runExecutable(entryPoint, []);
      })
      .then(flushThenExit)
      .catchError((e) {
        print("Excepción: $e");
      });
}Lenguaje del código: JavaScript (javascript)

3. Esperar varios Futures concurrentes

① Future.wait()

Espera a que todas las tareas finalicen; si falla cualquier Future, toda la operación falla inmediatamente

Future<void> task1() async {}
Future<void> task2() async {}
Future<void> task3() async {}

void testWait() async {
  await Future.wait([
    task1(),
    task2(),
    task3(),
  ]);
  print("Todas las tareas han finalizado");
}Lenguaje del código: JavaScript (javascript)
② List.wait / Record.wait (nuevas características, gestión detallada de errores concurrentes)

Lanza una excepción ParallelWaitError, permite distinguir qué tareas tuvieron éxito y cuáles fallaron, sin interrumpirse mutuamente.

Future<int> delete() async => 1;
Future<String> copy() async => "ok";
Future<bool> errorTask() async {
  throw Exception("Fallo en la tarea");
}

void main() async {
  try {
    // Formato de lista
    var results = await [delete(), copy(), errorTask()].wait;
  } on ParallelWaitError<List<Object?>, List<AsyncError?>> catch (e) {
    print(e.values);   // Contiene valores si tuvo éxito, null si falló
    print(e.errors);   // Null si tuvo éxito, almacena el error si falló
  }

  // Formato de tupla Record: admite Futures de tipos distintos
  try {
    final (resInt, resStr, resBool) = await (delete(), copy(), errorTask()).wait;
  } on ParallelWaitError<(int?, String?, bool?), (AsyncError?, AsyncError?, AsyncError?)> catch(e) {

  }
}Lenguaje del código: JavaScript (javascript)

Stream

Un Stream representa una serie continua de datos asíncronos (lectura línea a línea de archivos, eventos de clic en botones, flujos de red).

Dos formas principales de uso

1: await for bucle asíncrono (sintaxis compacta, similar a la iteración síncrona)

Ideal para flujos de datos finitos; no apto para flujos de eventos infinitos (como clics en interfaz), ya que bloquea el resto del código.

import 'dart:io';

Future<void> readFileByAwaitFor() async {
  var file = File("config.txt");
  Stream<List<int>> input = file.openRead();
  var lines = input
      .transform(utf8.decoder)
      .transform(const LineSplitter());

  try {
    await for (final line in lines) {
      print("Línea leída: $line");
    }
    print("Lectura del archivo completada");
  } catch (e) {
    print("Error de lectura $e");
  }
}Lenguaje del código: PHP (php)
2 .listen() suscripción y escucha (para flujos infinitos)
inputStream.listen(
  (data) {
    // Callback al recibir datos
  },
  onError: (err) {
    // Ocurre un error
  },
  onDone: () {
    // El flujo se cierra correctamente
  },
);Lenguaje del código: JavaScript (javascript)

listen devuelve un objeto StreamSubscription, desde el cual puedes llamar a .cancel() para anular la suscripción.

Métodos habituales para manipular Stream

  • Filtrado: where()
  • Límite de elementos: take(), takeWhile()
  • Saltar elementos: skip(), skipWhile()
  • Obtener un solo elemento: first, last, single, firstWhere()

Transformación de datos en Stream con transform()

Modifica el tipo de datos del flujo mediante transformadores (caso típico: convertir flujo binario a texto)

var lines = inputStream
    .transform(utf8.decoder)       // List<int> → String
    .transform(const LineSplitter()); // String → cadenas línea por líneaLenguaje del código: JavaScript (javascript)

Recomendación: elegir entre listen() y await for

  1. Lectura de archivos, secuencias de datos finitas → await for
  2. Eventos de interfaz, mensajes recibidos continuamente y otros flujos infinitos.listen()
  3. Una vez iniciado await for, esperará indefinidamente el fin del flujo; en flujos infinitos causará bloqueo del código

Librería dart:async

Previous:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *