异步支持
Dart
有一些语言特性来支持异步编程。 最常见的特性是 async
方法和 await
表达式。Dart
库中有很多返回 Future
或者 Stream
对象的方法。 这些方法是异步的: 这些函数在设置完基本的操作后就返回了, 而无需等待操作执行完成。 例如读取一个文件,在打开文件后就返回了。
处理Futures
有两种方式可以使用Future
对象中的数据:
- 使用
async
和await
- 使用 Future API
使用async
和await
的代码是异步的,不过它看起来很像同步的代码。比如这里有一段使用await
等待一个异步函数结果的代码:
await lookUpVersion();
要使用await
,其函数必须带有async
关键字:
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
你可以使用try, catch
, 和 finally
来处理错误
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
也可以在异步函数中多次使用await
,比如:下面代码使用了3次await
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
在await
表达式中,表达式的值经常是Future
,如果不是,那么其值将自动包裹成为Future
。Future
对象承若会返回一个对象。当对象被返回,await
表达式执行终止
当使用await
的时候有编译时错误的存在,应该确保await
是在异步函数中。例如:在mian()函数中使用await
,那么该函数必须被标记为async
:
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
声明异步方法
一个异步函数是一个由async
修饰符标记的函数。添加async
关键字标记函数将返回一个Future
。例如:考虑一下这个同步函数,它将返回一个字符串
String lookUpVersion() => '1.0.0';
如果我们修改函数为异步,因为在以后的实现中将会非常耗时-它的返回值是一个Future
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.
}
上面表达式返回的值必须是Stream
类型的。 执行流程如下:
- 1、等待直到
stream
返回一个数据 - 2、执行
for
循环的主体,把变量设置为发出的值。 - 3、重复执行 1 和 2 直到
stream
关闭
如果要停止监听stream
,你可以使用break
或者return
语句,跳出循环并取消来自stream
的订阅 。
如果一个异步for
循环没有正常运行,请确认它是一个异步方法。 比如,在应用的main()
方法中使用异步的for
循环时,main()
的方法体必须被async
标记。
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
更多关于异步编程的信息,请看 dart:async
库部分的介绍。你也可以看文章 Dart Language Asynchrony Support: Phase 1 和 Dart Language Asynchrony Support: Phase 2, 和 the Dart language specification
网友评论