Dart – 23 – async and await

Async and Await in Dart

Asynchronous programming is crucial for building responsive Dart applications, especially when dealing with time-consuming tasks like network requests or file operations. Dart provides the async and await keywords to simplify asynchronous code, making it more readable and maintaining the appearance of synchronous code. In this discussion, we’ll explore the significance of async and await, understand how they work, and see practical examples of their use.

The async Keyword

The async keyword is used to mark a function as asynchronous. It tells Dart that this function will perform asynchronous operations and may contain await expressions. Marking a function as async allows you to pause its execution while waiting for asynchronous tasks to complete without blocking the entire program.

Here’s an example of an async function:


Future fetchData() async {
  // Asynchronous operations go here
}
    
The await Keyword

The await keyword can only be used within a function marked as async. It is used to pause the execution of the function until an asynchronous operation, typically a Future, is completed. The result of the Future is returned and can be assigned to a variable.

Here’s an example of using await to fetch data from a Future:


Future fetchData() async {
  // Simulate an asynchronous operation
  await Future.delayed(Duration(seconds: 2));
  return 'Fetched Data';
}
    
Using async and await

Combining async and await in Dart simplifies asynchronous code, making it more readable and structured. You can use await to pause execution and retrieve the result of asynchronous tasks without needing to register callbacks or use then for handling Future results.

Here’s an example of using async and await to fetch and process data:


Future fetchDataAndProcess() async {
  try {
    final data = await fetchData();
    final processedData = await process(data);
    print('Processed Data: $processedData');
  } catch (error) {
    print('Error: $error');
  }
}

fetchDataAndProcess();
    
Multiple await Expressions

You can have multiple await expressions within a single async function. This allows you to pause and wait for multiple asynchronous tasks to complete, making it easy to perform multiple asynchronous operations in sequence.

Here’s an example of using multiple await expressions within an async function:


Future performMultipleTasks() async {
  final result1 = await task1();
  final result2 = await task2();
  final result3 = await task3();
  print('Results: $result1, $result2, $result3');
}
    
Error Handling with async and await

When working with asynchronous code using async and await, you can use try-catch blocks to handle errors gracefully. If an asynchronous task fails, the error will be caught by the nearest catch block.

Here’s an example of error handling with async and await:


Future fetchDataAndProcess() async {
  try {
    final data = await fetchData();
    final processedData = await process(data);
    print('Processed Data: $processedData');
  } catch (error) {
    print('Error: $error');
  }
}
    
Asynchronous Execution in Dart

By using async and await, Dart applications can remain responsive while performing time-consuming tasks. This is especially valuable for tasks like fetching data from the internet, reading and writing files, or any operation that may block the user interface.

Here’s an example of using async and await for fetching data from a web API:


import 'dart:async';
import 'dart:convert';
import 'http/http.dart' as http;

Future> fetchDataFromAPI() async {
  final response = await http.get(Uri.parse('https://api.example.com/data'));
  if (response.statusCode == 200) {
    return json.decode(response.body);
  } else {
    throw 'Failed to fetch data';
  }
}

fetchDataFromAPI().then((data) {
  print('Fetched Data: $data');
}).catchError((error) {
  print('Error: $error');
});
    
Conclusion

Asynchronous programming with async and await in Dart greatly simplifies the development of responsive and efficient applications. These keywords provide a structured way to work with asynchronous tasks, making it easier to read and maintain asynchronous code. Whether you’re dealing with network requests, file I/O, or other asynchronous operations, mastering async and await is essential for building Dart applications.