La librería dart:async proporciona las funcionalidades esenciales para la programación asíncrona en Dart: Future y Stream.
- No siempre es necesario importar manualmente
dart:asyncpara usarFuture / Stream, ya que dart:core ya lo exporta;- Si necesitas utilizar tipos como
StreamController,StreamSubscriptionoParallelWaitError, 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
asyncdevuelven un Future; awaitespera a que el Future finalice, pausando la ejecución hasta obtener el resultado;- Emplea
try-catchpara 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
- Lectura de archivos, secuencias de datos finitas →
await for - Eventos de interfaz, mensajes recibidos continuamente y otros flujos infinitos →
.listen() - Una vez iniciado await for, esperará indefinidamente el fin del flujo; en flujos infinitos causará bloqueo del código
Librería dart:async