Future 类型可以看作是对在将来完成任务或返回结果的一个承诺。
我们可以这样定义一个返回 Future 的方法声明。
Future<int> countStars();
从中可以看出,Future 是支持范型的,可以返回任意类型的值。
Future 有三个可能的状态:
- 未完成
- 成功完成,返回值
- 失败完成,返回错误
Dart 提供了两种方式得到 Future 返回的值:回调函数和async-await.
回调函数
回调函数是一个匿名函数,会在某个事件完成后被执行。Future 提供了三个回调函数:then, catchError 和 whenComplete.
void main(List<String> args) {
print('Future 执行前');
Future<int>.delayed(Duration(seconds: 1), () => 42)
.then((value) => print('返回值: $value'))
.catchError((Object error) => print('执行错误: $error'))
.whenComplete(() => print('Future 执行完毕'));
print('Future 执行后');
}
这里,Future<int>.delayed 返回一个 Future 的实例;使用 then 方法接收 Future 执行成功返回的值;使用 catchError 方法处理 Future 执行失败返回的错误;使用 whenComplete 方法处理 Future 执行完毕后的代码,也就是说,不论 Future 执行成功还是失败,whenComplete 方法中的代码都会执行。
运行上面的代码,我们会先得到下面的结果:
Future 执行前
Future 执行后
返回值: 42
Future 执行完毕
Exited.
Async‐Await
使用 Future 提供的三个回调函数处理返回值,会让我们面临一个问题:如果在回调函数中嵌套多层 Future 时,代码的可读性,可维护性会大大降低。
async 和 await 会让我们使用 Future 时,更像是在写同步代码。
Future<void> main(List<String> args) async {
print('Future 执行前');
final value = await Future<int>.delayed(
Duration(seconds: 1),
() => 42,
);
print('Value: $value');
print('Future 执行后');
}
这里,因为我们在 main 方法中使用了 await 关键字,那么 main 方法的声明必须返回 Future 并且添加 async 关键字。Dart 在执行带有 await 的 Future 语句时,他会一直等待 Future 返回结果,才继续执行下面的语句。
运行上面的代码,我们会先得到下面的结果:
Future 执行前
Value: 42
Future 执行后
Exited.
如果 Future 的执行出现了错误该如何处理呢?这时候,我们就需要使用 try-catch 语句了。
Future<void> main(List<String> args) async {
print('Future 执行前');
try {
final value = await Future<int>.delayed(
Duration(seconds: 1),
() => 42,
);
print('Value: $value');
} catch (error) {
print(error);
} finally {
print('Future 执行完毕');
}
print('Future 执行后');
}
运行上面的代码,我们会先得到下面的结果:
Future 执行前
Value: 42
Future 执行完毕
Future 执行后
Exited.
这里,catch 语句对应 catchError 回调函数;finally 语句对应 whenComplete 回调函数。