async/await in Depth
import 'dart:async';
Future<User> loadUser(String id) async {
final response = await http.get(Uri.parse('https://api.example.com/users/$id'));
if (response.statusCode != 200) {
throw HttpException('Failed: ${response.statusCode}');
}
return User.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
}
Future<void> main() async {
try {
final user = await loadUser('42');
print(user.name);
} on HttpException catch (e) {
print('HTTP error: $e');
} catch (e) {
print('Other error: $e');
}
}25.1 Sequential vs Parallel
// Sequential (slow): each waits for the previous one
final a = await fetchA();
final b = await fetchB();
// Parallel (fast): start both, then await
final futureA = fetchA();
final futureB = fetchB();
final (resA, resB) = await (futureA, futureB).wait;25.2 Async Pitfalls
Unawaited futures: errors can be lost. The unawaited_futures / discarded_futures lints catch this. Use unawaited(f) from dart:async to signal intent.
async in forEach: list.forEach((x) async => ...) doesn't wait. Use for loops or Future.wait.
Uncaught async errors: handle them with try/catch around await, .catchError, or zone handlers (Module 28).
Blocking the event loop: heavy synchronous computation freezes UI and I/O. Move it to an isolate (Module 27).
FutureOr<T> lets an API accept either a value or a Future.