Dart并发编程05-认识Future

32 阅读2分钟

Future 类型可以看作是对在将来完成任务或返回结果的一个承诺。

我们可以这样定义一个返回 Future 的方法声明。

Future<int> countStars();

从中可以看出,Future 是支持范型的,可以返回任意类型的值。

Future 有三个可能的状态:

  • 未完成
  • 成功完成,返回值
  • 失败完成,返回错误

Dart 提供了两种方式得到 Future 返回的值:回调函数和async-await.

回调函数

回调函数是一个匿名函数,会在某个事件完成后被执行。Future 提供了三个回调函数:then, catchErrorwhenComplete.

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 时,代码的可读性,可维护性会大大降低。

asyncawait 会让我们使用 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 在执行带有 awaitFuture 语句时,他会一直等待 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 回调函数。