Capturar errores con try
Parte de la sección Datos y red del Journey de Flutter de Coddy. Lección 10 de 27.
Una llamada de red puede fallar: el teléfono no tiene señal, el servidor está caído o la ruta es incorrecta. Cuando fetch falla, lanza un error: una ApiException, una clase pequeña al principio de api.dart con un statusCode y un message. Un error que nadie captura detiene tu función y aparece como un error rojo en la Consola, y la persona ve un indicador de carga que nunca termina.
Captúralo con try y catch:
try {
final text = await fetch('/message');
// solo se ejecuta cuando fetch funcionó
} catch (e) {
// solo se ejecuta cuando fetch lanzó una excepción
print('It failed: $e');
}Dart ejecuta el bloque try. Si algo dentro de él lanza un error, Dart salta directamente a catch, y e contiene el error. Las líneas posteriores a la que falla dentro de try nunca se ejecutan.
Coloca el propio await dentro de try: esa es la línea que lanza el error. Después, explícale a la persona qué ocurrió con palabras, en lugar de que la aplicación se cierre inesperadamente.
Para ver cómo falla en la vista previa, escribe offline = true; como primera línea de main y pulsa Run. offline viene de api.dart: hace que todas las llamadas fallen como si el teléfono no tuviera señal. Quita esa línea antes de pulsar Check.
Desafío
IntermedioHaz que loadMessage se recupere de una llamada fallida:
- coloca
fetchy elsetStateque va después en un bloquetry - en
catch (e), detén el indicador de carga y establece el mensaje comoCould not load: $e
Pruébalo tú mismo
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MessageScreen(),
);
}
}
class MessageScreen extends StatefulWidget {
const MessageScreen({super.key});
@override
State<MessageScreen> createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
String message = 'No message yet';
bool loading = false;
Future<void> loadMessage() async {
setState(() {
loading = true;
});
final text = await fetch('/message');
setState(() {
message = text;
loading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
loading
? const CircularProgressIndicator()
: Text(message, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 24),
ElevatedButton(onPressed: loadMessage, child: const Text('Load message')),
],
),
),
);
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Datos y red
3Cuando fallan las llamadas
Capturar errores con tryLanzar un errorLimpiar con finallyEl estado de error de FutureBuilderUn botón para volver a intentarloPractica por tu cuenta: Compilador de Flutter online