Concurrent Asynchronous Operations in Dart: A Guide to Future.wait
SR
Sabin Ranabhat
February 12, 2024•4 min read

Introduction:
Dart has provided a method “Future.wait” that provides an efficient way to handle multiple asynchronous operations concurrently. This is useful when you have several async functions that need to be executed before performing any operation. Please note that these async functions should be independent of each other.
Let’s consider you have to fetch data from 10 different APIs that are not dependent on each other. For the demo, I am using JSON Placeholder API to fetch To-dos.
Firstly, implement the API, it’s pretty simple.
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<Map<String, dynamic>> fetchTodoData(int todoId) async {
// Fetching todo data from the JSONPlaceholder API
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/todos/$todoId'),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to fetch todo data for todo ID $todoId');
}
}
On the second step, let’s create a list of API calls
// Create a list of asynchronous tasks to fetch todo data from different users
List<Future<Map<String, dynamic>>> apiCalls = [
fetchTodoData(1),
fetchTodoData(2),
fetchTodoData(3),
fetchTodoData(4),
fetchTodoData(5),
fetchTodoData(6),
fetchTodoData(7),
fetchTodoData(8),
fetchTodoData(9),
fetchTodoData(10),
];
Then, pass the list of API calls that we have created to the Future.wait() method. And then await for the result.
// Use Future.wait to wait for all API calls to complete
List<Map<String, dynamic>> results = await Future.wait(apiCalls);
// Log the results
for (int i = 0; i < results.length; i++) {
print("Todo data for user $i: ${jsonEncode(results[i])}");
}
Done, you have successfully implemented Future.wait() and handled multiple asynchronous operations efficiently.
You might be thinking, 'Aren’t we missing anything?' Yes, we are.
Error Handling.
On our async function we are throwing an exception, to handle that we need to surround Future.wait() with try catch block like this.
If you want to do some cleanup, then you can create a function where you handle cleanup. Clean up function is used for closing DB, file or any connection and so on.
Note: cleanup function will be only executed if any async function completes with an error.
Here’s the complete code:
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> main() async {
try {
// Create a list of API calls
List<Future<dynamic>> apiCalls = [];
for (int i = 1; i <= 10; i++) {
apiCalls.add(fetchTodoData(i));
}
// Wait for all API calls to complete
List<dynamic> results = await Future.wait(apiCalls);
// Process results
for (var result in results) {
print('Fetched Todo: ${result['title']}');
}
print('All operations completed successfully.');
} catch (e) {
print('Error occurred: $e');
cleanUpResources();
}
}
Future<Map<String, dynamic>> fetchTodoData(int todoId) async {
// Fetching todo data from the JSONPlaceholder API
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/todos/$todoId'));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to fetch todo data for todo ID $todoId');
}
}
void cleanUpResources() {
print('Cleaning up resources...');
// Close DB connections, files, etc.
}
In this example:
- fetchTodoData simulates an asynchronous operation of fetching data from the JSON Placeholder API.
- If the HTTP request is successful (status code 200), the response is parsed and returned as a list of to-dos.
- If the HTTP request fails or if there is a network-related error, an exception is thrown.
- The main function catches errors, prints an error message, and invokes the cleanUpResources function.
- The cleanUpResources function is a placeholder with a print statement. In a real-world scenario, this function should perform actual cleanup tasks, such as closing connections or releasing resources.
Comparing the execution time of Future.wait() with multiple await statements.
Fetching 10 APIs using Future.wait() method take only 31ms.
Using await
Output:
You can see that, Future.wait() does the same task a lot faster than using individual await on all each async function.
Conclusion:
In conclusion, Future.wait() method is a way more efficient for handling multiple async operations which are independent of each other. By using Future.wait, developers can streamline their code and enhance overall performance.
I hope you found this guide on Dart's Future.wait helpful! Your feedback matters. If you have questions, suggestions, or specific topics you'd like more coverage on, please leave a comment. Your insights help improve future content to better suit your needs. Thanks for reading! 🚀
Share this article:
Related Posts

Blog
February 22, 2024
Optimize Flutter Performance: Handle Heavy Image with Ease
Learn how to handle heavy images in Flutter using debugInvertOversizedImages and ResizeImage to optimize performance and memory usage.

Blog
February 4, 2024
Exploring Parallelism on Flutter: Main Thread, Isolate and Compute
Understanding the nuances of main thread, isolates, and compute empowers you to make informed decisions about concurrency in your Flutter projects.
© 2025 Sabin Ranabhat