Flutter Difference between async , await , future ?
#flutter#async#future
Answer
Overview
async, await, and Future are Dart's tools for handling asynchronous operations (operations that take time, like network requests, file I/O, database queries).
Future
Definition: A
text
FutureExample
dartFuture<String> fetchData() { return Future.delayed( Duration(seconds: 2), () => 'Data loaded', ); } void main() { print('Start'); fetchData(); // Returns immediately, doesn't block print('End'); // Prints before data loads // Output: // Start // End // (2 seconds later, data loads in background) }
async
Definition: Marks a function as asynchronous, meaning it can perform async operations and return a
text
FutureExample
dartFuture<String> fetchData() async { // Simulate network delay await Future.delayed(Duration(seconds: 2)); return 'Data loaded'; }
Key points:
- Functions marked automatically return atext
asynctextFuture - Can use insidetext
awaitfunctionstextasync - Must return a ortext
Future<T>textFuture<void>
await
Definition: Pauses execution of an
text
asynctext
FutureExample
dartFuture<void> loadData() async { print('Loading...'); String data = await fetchData(); // Waits for fetchData() to complete print('Loaded: $data'); } void main() async { await loadData(); print('Done'); // Output: // Loading... // (waits 2 seconds) // Loaded: Data loaded // Done }
Detailed Comparison
| Keyword | Purpose | Returns | Example |
|---|---|---|---|
| Future | Represents async result | Future | text |
| async | Marks function as async | Future | text |
| await | Waits for Future to complete | T (unwrapped value) | text |
How They Work Together
Without async/await (Using .then())
dartFuture<String> fetchData() { return Future.delayed(Duration(seconds: 2), () => 'Data'); } void main() { print('Start'); fetchData().then((data) { print('Loaded: $data'); }).catchError((error) { print('Error: $error'); }); print('End'); // Output: // Start // End // (2 seconds later) // Loaded: Data }
With async/await (Cleaner)
dartFuture<String> fetchData() async { await Future.delayed(Duration(seconds: 2)); return 'Data'; } void main() async { print('Start'); String data = await fetchData(); // Waits here print('Loaded: $data'); print('End'); // Output: // Start // (2 seconds later) // Loaded: Data // End }
Real-World Examples
Example 1: API Call
dartimport 'package:http/http.dart' as http; import 'dart:convert'; Future<List<User>> fetchUsers() async { final response = await http.get( Uri.parse('https://jsonplaceholder.typicode.com/users'), ); if (response.statusCode == 200) { final List<dynamic> data = jsonDecode(response.body); return data.map((json) => User.fromJson(json)).toList(); } else { throw Exception('Failed to load users'); } } // Usage void main() async { try { List<User> users = await fetchUsers(); print('Loaded ${users.length} users'); } catch (e) { print('Error: $e'); } }
Example 2: Multiple Async Operations (Sequential)
dartFuture<void> loadUserData() async { print('Fetching user...'); User user = await fetchUser(); // Wait for user print('Fetching user posts...'); List<Post> posts = await fetchUserPosts(user.id); // Wait for posts print('User: ${user.name}, Posts: ${posts.length}'); }
Example 3: Multiple Async Operations (Parallel)
dartFuture<void> loadDashboard() async { print('Loading dashboard...'); // Run both API calls in parallel final results = await Future.wait([ fetchUser(), fetchPosts(), fetchComments(), ]); final user = results[0] as User; final posts = results[1] as List<Post>; final comments = results[2] as List<Comment>; print('Loaded user, ${posts.length} posts, ${comments.length} comments'); }
Example 4: Timeout
dartFuture<String> fetchDataWithTimeout() async { try { return await fetchData().timeout(Duration(seconds: 5)); } on TimeoutException { return 'Request timed out'; } }
Error Handling
Using try-catch
dartFuture<void> loadData() async { try { String data = await fetchData(); print('Success: $data'); } catch (e) { print('Error: $e'); } finally { print('Cleanup'); } }
Using .catchError()
dartvoid loadData() { fetchData() .then((data) => print('Success: $data')) .catchError((error) => print('Error: $error')); }
Flutter Example (Async in Widgets)
FutureBuilder
dartclass UserProfile extends StatelessWidget { Widget build(BuildContext context) { return FutureBuilder<User>( future: fetchUser(), // Async operation builder: (context, snapshot) { // Loading if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); } // Error if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } // Success if (snapshot.hasData) { final user = snapshot.data!; return Text('User: ${user.name}'); } return Text('No data'); }, ); } }
StatefulWidget with async
dartclass UserPage extends StatefulWidget { _UserPageState createState() => _UserPageState(); } class _UserPageState extends State<UserPage> { User? _user; bool _isLoading = false; String? _error; void initState() { super.initState(); _loadUser(); } Future<void> _loadUser() async { setState(() => _isLoading = true); try { final user = await fetchUser(); setState(() { _user = user; _isLoading = false; }); } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } Widget build(BuildContext context) { if (_isLoading) return CircularProgressIndicator(); if (_error != null) return Text('Error: $_error'); if (_user == null) return Text('No user'); return Text('User: ${_user!.name}'); } }
Common Patterns
Pattern 1: Return Early on Error
dartFuture<String?> fetchData() async { try { final response = await http.get(url); if (response.statusCode != 200) return null; return response.body; } catch (e) { return null; } }
Pattern 2: Chain Multiple Async Calls
dartFuture<void> processData() async { final data = await fetchData(); final processed = await processData(data); final result = await saveData(processed); print('Done: $result'); }
Pattern 3: Retry Logic
dartFuture<String> fetchWithRetry({int maxRetries = 3}) async { for (int i = 0; i < maxRetries; i++) { try { return await fetchData(); } catch (e) { if (i == maxRetries - 1) rethrow; // Last attempt failed await Future.delayed(Duration(seconds: 2)); // Wait before retry } } throw Exception('All retries failed'); }
Future States
dartFuture<String> fetchData() async { await Future.delayed(Duration(seconds: 2)); return 'Data'; } void main() async { final future = fetchData(); print(future); // Instance of 'Future<String>' (uncompleted) final result = await future; print(result); // 'Data' (completed) }
States:
- Uncompleted - Operation in progress
- Completed with value - Success
- Completed with error - Failure
Async vs Sync Comparison
Synchronous (Blocks)
dartString fetchDataSync() { // Blocks for 2 seconds sleep(Duration(seconds: 2)); return 'Data'; } void main() { print('Start'); String data = fetchDataSync(); // Waits here (UI freezes!) print('Data: $data'); print('End'); }
Asynchronous (Non-blocking)
dartFuture<String> fetchDataAsync() async { // Doesn't block await Future.delayed(Duration(seconds: 2)); return 'Data'; } void main() async { print('Start'); String data = await fetchDataAsync(); // Waits, but doesn't block UI print('Data: $data'); print('End'); }
Key Differences
| Feature | Synchronous | Asynchronous |
|---|---|---|
| Blocks UI | ✅ Yes | ❌ No |
| Returns | Value directly | Future |
| Use case | Fast operations | Slow operations (network, I/O) |
| Execution | Sequential | Can run in parallel |
Best Practices
| Practice | Recommendation |
|---|---|
| Use async/await | Cleaner than .then() callbacks |
| Handle errors | Always use try-catch |
| Don't block UI | Never use synchronous I/O |
| Parallel operations | Use Future.wait() when possible |
| Timeout | Set timeouts for network requests |
| Test async code | Use text |
Common Mistakes
❌ Mistake 1: Forgetting await
dart// ❌ Bad - doesn't wait void loadData() async { fetchData(); // Doesn't wait! print('Done'); // Prints immediately } // ✅ Good void loadData() async { await fetchData(); // Waits print('Done'); // Prints after data loads }
❌ Mistake 2: Not marking function as async
dart// ❌ Error - can't use await without async void loadData() { await fetchData(); // Error! } // ✅ Good Future<void> loadData() async { await fetchData(); }
❌ Mistake 3: Forgetting to return Future
dart// ❌ Bad - should return Future<void> async void loadData() { await fetchData(); } // ✅ Good Future<void> loadData() async { await fetchData(); }
Key Takeaways
Future: Represents a value available in the future (async result)
async: Marks a function as asynchronous (can use await)
await: Waits for Future to complete, returns unwrapped value
Use together:
textFuture<T> functionName() async { await ... }