异步支持

Last updated: ... / Reads: 39 Edit

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

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

处理期货

当您需要完整 Future 的结果时,您有两种选择:

  • 使用 async 和 await ,如此处和异步编程 Codelab 中所述。
  • 使用 Future API,如 dart:async 文档中所述。

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

await lookUpVersion();

要使用 await ,代码必须位于 async 函数中 - 标记为 async 的函数:

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

虽然 async 函数可能执行耗时的操作,但它不会等待这些操作。相反, async 函数仅执行到遇到第一个 await 表达式为止。然后它返回一个 Future 对象,仅在 await 表达式完成后恢复执行。

使用 try 、 catch 和 finally 处理使用 await 的代码中的错误和清理:

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

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

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

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

如果您在使用 await 时遇到编译时错误,请确保 await 在 async 函数中。例如,要在应用的 main() 函数中使用 await , main() 的正文必须标记为 async :

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

前面的示例使用 async 函数 ( checkVersion() ) 而不等待结果 - 如果代码假定函数已完成执行,这种做法可能会导致问题。为了避免此问题,请使用 unwaited_futures linter 规则。

有关使用 future、 async 和 await 的交互式介绍,请参阅异步编程 Codelab。

声明异步函数

async 函数是其主体用 async 修饰符标记的函数。

将 async 关键字添加到函数中会使其返回 Future。例如,考虑这个同步函数,它返回一个字符串:

String lookUpVersion() => '1.0.0';=

如果将其更改为 async 函数(例如,因为未来的实现将非常耗时),则返回值是 Future:

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

请注意,函数的主体不需要使用 Future API。如果需要,Dart 会创建 Future 对象。如果您的函数不返回有用的值,请将其返回类型设置为 Future

有关使用 future、 async 和 await 的交互式介绍,请参阅异步编程 Codelab。

处理流

当您需要从 Stream 获取值时,您有两种选择:

  • 使用 async 和异步 for 循环 ( await for )。
  • 使用 Stream API,如 dart:async 文档中所述。

在使用 await for 之前,请确保它使代码更清晰并且您确实想要等待所有流的结果。例如,您通常不应该使用 await for 作为 UI 事件侦听器,因为 UI 框架会发送无穷无尽的事件流。

异步 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 循环并取消订阅流。

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

void main() async {
  // ...
  await for (final request in requestServer) {
    handleRequest(request);
  }
  // ...
}

有关 Dart 异步编程支持的更多信息,请查看 dart:async 库文档。


Comments

Make a comment