异步支持
异步编程使用 async 和 await 关键字实现。 让你可以像编写同步代码一样实现异步操作。
许多返回 Future 或 Stream 对象的函数包含Dart 库中. 这些函数在设置完耗时任务(例如 I/O 曹组)后,不等它完成 就立即返回了。
处理 Future
获得 Future 执行完成的结果,通过以下方式:
使用 async 和 await.
使用 Future API
虽然看起来像是同步代码,但是async 和 await 关键字的代码是异步的。 如下使用 await 等待异步函数的执行结果。
await lookUpVersion();
代码必须在 异步函数(使用 async 标记的函数)中,才能使用await :
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
提示: 异步函数只有在遇到第一个 await 表达式时才会执行。异步函数可能会执行耗时的操作, 但它不会等待这些操作。
代码中使用 await 导致的错误,使用 try, catch, 和 finally 来处理。
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 对象指明返回一个对象的承诺(promise)。 await 表达式 执行的结果为这个返回的对象。 await 表达式会阻塞代码的执行,直到需要的对象返回为止。
如果在使用 await 导致编译时错误, 确认 await 是否在一个异步函数中。 例如,在应用的 main() 函数中使用 await , main() 函数的函数体必须被标记为 async :
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
声明异步函数
函数体被 async 标示符标记的函数是一个异步函数。 将 async 关键字添加到函数使其返回Future。 例如,考虑下面的同步函数,返回一个 String :
String lookUpVersion() => '1.0.0';
例如,将来的实现将非常耗时,将其更改为异步函数,返回值是 Future 。
Future<String> lookUpVersion() async => '1.0.0';
注意,函数体不需要使用Future API。 如有必要, Dart 会创建 Future 对象。
如果函数没有返回有效值, 需要设置其返回类型为 Future 。
处理 Stream
可以通过以下两种方式从 Stream 中获取数据值:
- 使用 async 和 一个 异步循环 (await for)。
- 使用 Stream API
在使用 await for 前,确保代码清晰, 并且确实希望等待所有流的结果。 例如,通常不应该使用 await for 的UI事件侦听器, 因为UI框架会发送无穷无尽的事件流。
以下是异步for循环的使用形式:
await for (varOrType identifier in expression) {
// Executes each time the stream emits a value.
}
上面 表达式 返回的值必须是 Stream 类型。 执行流程如下:
- 等待,直到流发出一个值。
- 执行 for 循环体,将变量设置为该发出的值
- 重复1和2,直到关闭流。
停止接收 stream 的数据可以使用 break 或者 return 语句, 这样就跳出了 for 循环, 并从 stream 上取消注册。 确保 await for 处于异步函数中,防止在实现异步 for 循环时遇到编译时错误。 例如,要在应用程序的 main() 函数中使用异步 fo r循环, main() 函数体必须标记为 async` :
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}