Dart 基础之异步支持

Dart库充满了返回 FutureStream 对象的函数。 这些函数都是异步的:它们在设置可能耗时的操作(例如I/O)之后返回,而无需等待该操作完成。

asyncawait 关键字支持异步编程,使你可以编写 看起来类似于同步代码的 异步代码。

处理Futures

当你需要一个已经完成的 Future 结果,可以有两个方式:

  • asyncawait
  • 用 Future API, 在库描述中可以找到

使用 asyncawait 的代码是异步的,但是看起来很像同步代码。 例如,下面是一些使用 await 等待异步函数结果的代码:

await lookUpVersion();
复制代码

要使用 await 代码必须位于 async 函数中 ,该函数被标记为 async

Future checkVersion() async {
  var version = await lookUpVersion();
  // 用version干些事情
}
复制代码

注意:尽管异步功能可能会执行耗时的操作,但它不会等待这些操作。 相反,异步函数仅在遇到第一个await表达式( 详情 )之前执行。 然后,它返回Future对象,仅在await表达式完成后才恢复执行。

使用 trycatchfinally 去处理错误,并且使用 await 清理代码

try {
  version = await lookUpVersion();
} catch (e) {
  // 应对 lookUpVersion()失败的情况
}
复制代码

你可以在 async 函数中多次使用 await 。 例如,以下代码等待三遍函数结果:

var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
复制代码

await表达式 中, 表达式 的值通常是Future; 如果不是,则该值将自动包装在Future中。 此Future对象指示返回一个对象的承诺。 await表达式 的值是返回的对象。 await表达式使执行暂停,直到该对象可用为止。

**如果在使用 await 时收到编译时错误,请确保 awaitasync 函数中。**例如,要在应用程序的 main() 函数中使用 await ,必须将 main() 的正文标记为 async

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

定义异步函数

async 函数是一个主体带有 async 修饰符的函数。

向函数添加 async 关键字使其返回Future。 例如,考虑以下同步函数,该函数返回一个String:

String lookUpVersion() => '1.0.0';
复制代码

如果将其更改为 async 函数(例如,由于将来的实现会很耗时),则返回的值将为Future:

Future<String> lookUpVersion() async => '1.0.0';
复制代码

请注意,该函数的主体不需要使用Future API。 Dart会在必要时创建Future对象。 如果你的函数没有返回有用的值,请使其返回类型为 Future<void>

有关使用futures,async和await的交互式介绍,请参见异步编程代码实验室。

处理流

当你需要从流中获取值,你有两种方式:

  • async 和一个异步的for循环( await for )
  • 用Stream API, 在库描述中可以找到

注意:在使用 await 之前,请确保它使代码更清晰,并且你确确实实要等待所有流的结果。 例如,你通常不应将 await 用于UI事件侦听器,因为UI框架发送无休止的事件流。

一个异步循环有以下格式:

await for (varOrType identifier in expression) {
  // 每次执行steam(流)都会发出一个值。
}
复制代码

表达式 的值必须具有Stream类型。 执行过程如下:

  1. 会等到流发出一个值为止
  2. 执行for循环体,并将变量设置为该发射值。
  3. 重复1和2,直到关闭流。

要停止监听流,可以使用 breakreturn 语句,该语句会脱离for循环并取消订阅流。

如果在实现异步for循环时遇到编译时错误,请确保 await for 位于 async 函数中。 例如,要在应用程序的 main() 函数中使用异步for循环,必须将 main() 的正文标记为 async

Future main() async {
  // ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  // ...
}
复制代码

通常,有关异步编程的更多信息,请参见库介绍的dart:async部分。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章