Futures & async/await
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 76 of 110.
In real applications, many operations take time - fetching data from a server, reading files, or waiting for user input. Dart handles these with Future, which represents a value that will be available sometime in the future.
A Future is like a promise: "I'll give you the result when it's ready." You can create one using Future.delayed() to simulate an operation that takes time:
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}To work with the result of a Future, use async and await. Mark your function as async, then use await to pause execution until the Future completes:
Future<void> main() async {
print('Fetching user...');
String name = await fetchUserName();
print('Hello, $name!');
}
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}Without await, you'd get a Future<String> instead of the actual string. The await keyword unwraps the Future and gives you the value inside. Note that any function using await must be marked async, and it automatically returns a Future.
You can also return values directly from async functions - Dart wraps them in a Future automatically:
Future<int> calculateTotal() async {
var a = await fetchNumber();
var b = await fetchNumber();
return a + b; // Automatically wrapped in Future<int>
}Challenge
EasyLet's build a weather service that simulates fetching weather data from different cities! You'll practice using Future, async, and await to handle operations that take time to complete.
You'll organize your code into two files:
weather_service.dart: Create aWeatherServiceclass that simulates fetching weather information. Your class should have:- A method
fetchTemperature(String city)that returns aFuture<int>. UseFuture.delayed()with a duration of 100 milliseconds to simulate network delay. The method should return a temperature based on the city name: return the length of the city name multiplied by 3. - A method
fetchCondition(String city)that returns aFuture<String>. UseFuture.delayed()with 100 milliseconds delay. Return'Sunny'if the city name has an even number of characters, otherwise return'Cloudy'. - An async method
getFullReport(String city)that returns aFuture<String>. This method should await bothfetchTemperatureandfetchCondition, then return a formatted string:'[city]: [temperature]C, [condition]'
- A method
main.dart: Import your weather service and demonstrate how async operations work. Your main function should be async and:- Create a
WeatherServiceinstance - Print
Fetching weather data... - Await and print the full report for
'Paris' - Await and print the full report for
'Tokyo' - Await and print the full report for
'London' - Print
Done!
- Create a
Notice how each call to getFullReport waits for both the temperature and condition to be fetched before returning the combined result. The await keyword pauses execution until each Future completes!
Expected output:
Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!Cheat sheet
A Future represents a value that will be available in the future. It's used for operations that take time, like fetching data or reading files.
Create a Future using Future.delayed():
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}Use async and await to work with Futures. Mark the function as async and use await to pause execution until the Future completes:
Future<void> main() async {
print('Fetching user...');
String name = await fetchUserName();
print('Hello, $name!');
}The await keyword unwraps the Future and gives you the actual value. Without it, you'd get a Future<String> instead of the string.
Any function using await must be marked async and automatically returns a Future.
Return values from async functions are automatically wrapped in a Future:
Future<int> calculateTotal() async {
var a = await fetchNumber();
var b = await fetchNumber();
return a + b; // Automatically wrapped in Future<int>
}Try it yourself
import 'weather_service.dart';
Future<void> main() async {
// TODO: Create a WeatherService instance
// TODO: Print 'Fetching weather data...'
// TODO: Await and print the full report for 'Paris'
// TODO: Await and print the full report for 'Tokyo'
// TODO: Await and print the full report for 'London'
// TODO: Print 'Done!'
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor12Async OOP
Futures & async/awaitStreams BasicsStream ControllersAsync ConstructorsAsync in Class MethodsRecap - Data Fetcher