What are async/await?
async and await are syntactic sugar over Futures that make asynchronous code look and behave like synchronous code. An async function always returns a Future, even if you return a plain value.
Syntax
// Mark function as async:
Future<String> fetchUser(int id) async {
// await pauses execution until the Future completes:
await Future.delayed(Duration(seconds: 1));
return 'User $id';
}
void main() async {
print('Fetching...');
String user = await fetchUser(42);
print(user); // User 42
print('Done');
}
// Output: Fetching... → (1 second) → User 42 → Done
Error Handling with try-catch
Future<String> riskyFetch() async {
await Future.delayed(Duration(milliseconds: 200));
throw Exception('Server error');
}
Future<void> main() async {
try {
var result = await riskyFetch();
print(result);
} catch (e) {
print('Caught: $e'); // Caught: Exception: Server error
} finally {
print('Cleanup');
}
}
Parallel vs Sequential
Future<String> task(String name, int seconds) async {
await Future.delayed(Duration(seconds: seconds));
return '$name done';
}
Future<void> sequential() async {
var t = DateTime.now();
var a = await task('A', 2); // waits 2s
var b = await task('B', 2); // waits another 2s
print([a, b]);
print('Sequential: $${DateTime.now().difference(t).inSeconds}s'); // ~4s
}
Future<void> parallel() async {
var t = DateTime.now();
// Start both immediately:
var futureA = task('A', 2);
var futureB = task('B', 2);
var results = await Future.wait([futureA, futureB]);
print(results);
print('Parallel: $${DateTime.now().difference(t).inSeconds}s'); // ~2s
}
Full Example: HTTP-like API Calls
class ApiClient {
Future<Map<String, dynamic>> getUser(int id) async {
await Future.delayed(Duration(milliseconds: 300));
return {'id': id, 'name': 'User $id', 'email': 'user$id@example.com'};
}
Future<List<String>> getPosts(int userId) async {
await Future.delayed(Duration(milliseconds: 200));
return List.generate(3, (i) => 'Post $${i + 1} by user $userId');
}
}
Future<void> main() async {
var client = ApiClient();
// Get user, then their posts
var user = await client.getUser(1);
print('User: $${user['name']}');
var posts = await client.getPosts(user['id']);
for (var post in posts) {
print(' - $post');
}
// Or get multiple users in parallel:
var users = await Future.wait(
[1, 2, 3].map(client.getUser),
);
print('Loaded $${users.length} users');
}
Output:User: User 1
- Post 1 by user 1
- Post 2 by user 1
- Post 3 by user 1
Loaded 3 users
🧠 Quiz
1. What does an async function always return?
- A) void
- B) dynamic
- C) A Future ✅
- D) A Stream
2. How do you run two async tasks in parallel?
- A) await task1(); await task2();
- B) var f1 = task1(); var f2 = task2(); await Future.wait([f1, f2]); ✅
- C) await [task1(), task2()]
- D) Future.parallel([task1, task2])
Summary
Mark functions async and use await to pause until a Future completes. Async functions always return Future<T>. Use try-catch for error handling. For parallel execution, start all futures first then await Future.wait() — don't await them one by one.