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
回调函数。