Future 与 async/await
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 76 课,共 110 课。
在实际应用中,许多操作都需要时间,比如从服务器获取数据、读取文件或等待用户输入。Dart 使用 Future 处理这些操作,它表示一个未来某个时刻才能获取的值。
Future 就像一个承诺:“准备好后,我会把结果给你。”你可以使用 Future.delayed() 创建一个 Future,模拟一个需要花费时间的操作:
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}要处理 Future 的结果,请使用 async 和 await。将函数标记为 async,然后使用 await 暂停执行,直到 Future 完成:
Future<void> main() async {
print('Fetching user...');
String name = await fetchUserName();
print('Hello, $name!');
}
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}如果不使用 await,你得到的会是 Future<String>,而不是真正的字符串。await 关键字会解包 Future,并给你其中的值。请注意,使用 await 的函数必须标记为 async,并且会自动返回一个 Future。
你也可以从 async 函数中直接返回值,Dart 会自动将它们包装在 Future 中:
Future<int> calculateTotal() async {
var a = await fetchNumber();
var b = await fetchNumber();
return a + b; // 自动包装为 Future<int>
}挑战
简单我们来构建一个天气服务,模拟从不同城市获取天气数据!你将练习使用 Future、async 和 await 来处理需要时间才能完成的操作。
你将把代码分成两个文件:
weather_service.dart:创建一个WeatherService类,用来模拟获取天气信息。这个类应包含:- 一个方法
fetchTemperature(String city),返回Future<int>。使用Future.delayed(),设置持续时间为 100 毫秒,以模拟网络延迟。该方法应根据城市名称返回温度:返回城市名称的长度乘以 3。 - 一个方法
fetchCondition(String city),返回Future<String>。使用Future.delayed(),设置延迟为 100 毫秒。如果城市名称的字符数是偶数,就返回'Sunny',否则返回'Cloudy'。 - 一个异步方法
getFullReport(String city),返回Future<String>。该方法应等待fetchTemperature和fetchCondition都完成,然后返回格式化后的字符串:'[city]: [temperature]C, [condition]'
- 一个方法
main.dart:导入天气服务,并演示异步操作的工作方式。你的主函数应为异步函数,并且需要:- 创建一个
WeatherService实例 - 打印
Fetching weather data... - 等待并打印
'Paris'的完整报告 - 等待并打印
'Tokyo'的完整报告 - 等待并打印
'London'的完整报告 - 打印
Done!
- 创建一个
注意,每次调用 getFullReport 时,都会等待温度和天气状况都获取完成后,才返回合并后的结果!await 关键字会暂停执行,直到每个 Future 完成。
预期输出:
Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!亲手试试
import 'weather_service.dart';
Future<void> main() async {
// TODO: 创建一个 WeatherService 实例
// TODO: 打印 'Fetching weather data...'
// TODO: 等待并打印 'Paris' 的完整报告
// TODO: 等待并打印 'Tokyo' 的完整报告
// TODO: 等待并打印 'London' 的完整报告
// TODO: 打印 'Done!'
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器