Dart之旅10: 异步支持

dart中充满了返回FutureStream对象的方法。这些方法是异步的:它们设置了一个耗时操作之后就会直接返回,而不是等待操作完成。

asyncawait关键字支持异步编程,并且让你编写看起来像是同步编程一样的代码。

处理Future

当你需要Future的执行结果时,你有两种选择:

  • 使用asyncawait
  • 使用Future的API,在library tour中有详细描述。

代码使用asyncawait是异步的,但是它看起来像是同步代码。例如,这里有代码使用await来等待异步方法的结果。

await lookUpVersion();

如果想要使用await,代码必须使用异步方法——用async标记的方法:

Future checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}

注意:虽然异步方法会执行一个耗时操作,但它不会等待那些操作,一个async方法会执行到第一个await表达式,然后它会返回一个Future对象,用来处理await中操作的结果。

使用try-catch-finally来对await表达式进行异常处理:

try {
  version = await lookUpVersion();
} catch (e) {
  // React to inability to look up the version
}

你可以在一个方法中多次使用await

var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);

在await表达式中,表达式的值通常是一个Future;如果不是,那么这个将会自动包装在Future中。这个Future对象指代了一个返回对象的约定(类似Java的Future类)。await表达式的值就是那个Future返回的值。await会在Future返回之前阻塞代码的执行。

如果你得到了一个编译时错误,那么你要确保你的await是在async方法中使用的,例如在main方法中使用await就要把main()方法标记为async

Future main() async {
  checkVersion();
  print('In main: version is ${await lookUpVersion()}');
}

声明异步方法

异步方法需要添加async修饰符标识。例如你想将下面的函数变成异步方法:

String lookUpVersion() => '1.0.0';

那么你可以这样写:

Future<String> lookUpVersion() async => '1.0.0';

注意方法体内部并没有必要使用Future API,如果有必要的话dart会创建一个Future对象。

如果你的异步方法没有返回一个有用的值,那他会返回类型Future<void>.

处理流

当你需要处理一个来自Stream的值,那么你有两种选择:

  • 使用async和一个异步的for循环(await for)。
  • 使用Stream的API

异步for循环的写法如下:

await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}

expression的值必须是Stream类型。执行过程如下

  1. 等待流发射值
  2. 执行for循环,并将变量设置为流发射的值
  3. 重复1和2步骤

想要停止监听流,可以使用break或者return语句,它们可以跳出for循环,并且取消对流的订阅。

await表达式一样await for也需要函数体使用async包裹,否则可能会出现编译时错误:

Future main() async {
  // ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  // ...
}
    原文作者:suikaJY
    原文地址: https://www.jianshu.com/p/13a2979afa9c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞