Programacion Asincrona
## Objetivos de Aprendizaje
- Comprender conceptos de programacion asincrona
- Dominar Future y async/await
- Trabajar con Streams
- Manejar errores en codigo asincrono
## Por Que Asincrono?
### El Problema
```dart
// Sincrono - bloquea hasta completar
void main() {
print('Antes');
var data = fetchData(); // Bloquea por 5 segundos
print(data);
print('Despues');
}
```
### La Solucion
```dart
// Asincrono - no bloquea
void main() async {
print('Antes');
var data = await fetchData(); // No bloquea
print(data);
print('Despues');
}
```
## Future
### Concepto Basico
```dart
void main() {
// simular operacion asincrona
Future fetchData() {
return Future.delayed(Duration(seconds: 2), () {
return 'Datos cargados';
});
}
print('Antes');
fetchData().then((data) {
print(data); // Datos cargados
});
print('Despues'); // Se imprime antes que los datos (no bloquea)
}
```
### Estados de Future
1. **Incompleto**: Operacion en progreso
2. **Completado con valor**: Exito
3. **Completado con error**: Falla
## async y await
### Sintaxis Basica
```dart
Future fetchUser() async {
// Simular retraso de red
await Future.delayed(Duration(seconds: 1));
return 'Alice';
}
void main() async {
print('Obteniendo...');
String user = await fetchUser();
print('Usuario: $user');
}
```
### Reglas de Funciones async
```dart
// funcion async siempre devuelve Future
Future addOne(int n) async {
await Future.delayed(Duration(milliseconds: 100));
return n + 1;
}
// void async - solo para efectos secundarios
Future process() async {
await Future.delayed(Duration(seconds: 1));
print('Hecho');
}
```
### Multiples awaits
```dart
Future loadData() async {
print('Cargando...');
var user = await fetchUser();
var posts = await fetchPosts(user);
print('Usuario: $user');
print('Publicaciones: $posts');
}
```
## Manejo de Errores
### Try-Catch
```dart
Future fetchData() async {
try {
var result = await riskyOperation();
print('Exito: $result');
} catch (e) {
print('Error: $e');
}
}
Future riskyOperation() async {
await Future.delayed(Duration(seconds: 1));
throw Exception('Fallo!');
}
```
### Capturar Errores Especificos
```dart
Future process() async {
try {
await fetchData();
} on NetworkException {
print('Error de red');
} on ServerException catch (e) {
print('Error de servidor: $e');
} catch (e, stack) {
print('Inesperado: $e');
print('Stack: $stack');
}
}
class NetworkException implements Exception {}
class ServerException implements Exception {
final String message;
ServerException(this.message);
}
```
### Finally
```dart
Future process() async {
try {
await fetchData();
} catch (e) {
print('Error: $e');
} finally {
// Siempre se ejecuta
await cleanup();
}
}
```
## Metodos de Future
### then
```dart
Future fetchNumber() async {
return 42;
}
void main() {
fetchNumber()
.then((n) => n * 2)
.then((n) => print('Resultado: $n')); // Resultado: 84
}
```
### catchError
```dart
Future fetchNumber() async {
throw Exception('Error');
}
void main() {
fetchNumber()
.catchError((e) => print('Capturado: $e'))
.then((n) => print('Numero: $n')); // Capturado: Exception: Error
}
```
### whenComplete
```dart
Future process() async {
await fetchData()
.whenComplete(() => print('Limpieza completada'));
}
```
### wait
```dart
Future main() async {
var futures = [
fetchUser(1),
fetchUser(2),
fetchUser(3),
];
var results = await Future.wait(futures);
print('Todos los usuarios: $results');
}
```
## Streams
### Basicos de Stream
```dart
Stream countStream() async* {
for (int i = 1; i <= 5; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void main() async {
await for (var value in countStream()) {
print(value); // 1, 2, 3, 4, 5 (cada segundo)
}
print('Hecho');
}
```
### Metodos de Stream
```dart
void main() {
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
// listen
stream.listen((value) {
print('Recibido: $value');
});
// map
stream.map((n) => n * 2);
// where
stream.where((n) => n % 2 == 0);
// take
stream.take(3);
}
```
### Streams de Suscripcion Unica
```dart
Stream countStream() async* {
for (int i = 1; i <= 5; i++) {
yield i;
}
}
void main() async {
var stream = countStream();
// Solo puede escucharse una vez
stream.listen(print);
// stream.listen(print); // Error: ya se esta escuchando
}
```
### Streams de Difusion
```dart
class EventBus {
final _controller = StreamController.broadcast();
Stream get stream => _controller.stream;
void emit(String event) {
_controller.add(event);
}
void dispose() {
_controller.close();
}
}
void main() {
var bus = EventBus();
bus.stream.listen((e) => print('Escuchador 1: $e'));
bus.stream.listen((e) => print('Escuchador 2: $e'));
bus.emit('Hola'); // Ambos escuchadores reciben
bus.dispose();
}
```
## Patrones Asincronos
### FutureBuilder (Flutter)
```dart
// Ejemplo Flutter
FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text('Datos: ${snapshot.data}');
}
},
)
```
### StreamBuilder (Flutter)
```dart
// Ejemplo Flutter
StreamBuilder(
stream: countStream(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return Text('Conteo: ${snapshot.data}');
},
)
```
## Operaciones Asincronas Comunes
### timeout
```dart
Future fetchData() async {
return Future.delayed(Duration(seconds: 5), () => 'Datos');
}
void main() async {
try {
var result = await fetchData().timeout(
Duration(seconds: 2),
onTimeout: () => 'Valor por defecto de timeout',
);
print(result); // Valor por defecto de timeout
} catch (e) {
print('Error: $e');
}
}
```
### retry
```dart
Future fetchWithRetry() async {
for (int i = 0; i < 3; i++) {
try {
return await fetchData();
} catch (e) {
if (i == 2) rethrow;
await Future.delayed(Duration(seconds: 1));
}
}
throw Exception('Fallo');
}
```
## Async vs Sync
| Aspecto | Async | Sync |
|--------|-------|------|
| Bloqueante | No | Si |
| Devuelve | Future | Valor |
| Palabra clave | async/await | Ninguna |
| Error | try/catch | try/catch |
| Caso de uso | I/O, red | Computacion |
## Resumen
- Future: representa un valor disponible en algun momento posterior
- `async` hace que la funcion devuelva Future
- `await` pausa hasta que Future complete
- Streams: secuencia de eventos asincronos
- `async*` produce multiples valores desde stream
- `listen` subscribe a streams
- Manejar errores con try/catch
- `StreamController` crea streams programaticamente
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →