异步支持

最后更新于:2022-04-02 04:59:25

[TOC] Dart库中有非常多的函数返回Future对象或Stream对象。这些函数是异步的:在可能耗时的操作(例如I/O)操作的语句之后不等到操作执行完成就返回。 async和await关键字支持异步编程,允许您编写类似于同步代码的异步代码。 ## 处理Futures 当你需要一个完整的Futures的结果时,你有两个选择: * 使用async和await * 使用Future的API,如[库的引导]中描述的一样 使用async和await的代码虽然是异步的,但是看起来很像同步代码。例如,以下代码使用await来等待异步函数执行的结果: ~~~ await lookUpVersion(); ~~~ 要使用await必须是对一个使用async标注的异步函数: ~~~ Future checkVersion() async { var version = await lookUpVersion(); // Do something with version } ~~~ >注意:尽管异步函数可能执行耗时的操作,但它不会等待这些操作。相反,异步函数一直执行直到遇到第一个await表达式([查看详细信息])。然后它返回一个Futures的对象,只有在await表达式完成之后才恢复执行。 > Use try, catch, and finally to handle errors and cleanup in code that uses await: 使用try,catch和finally来处理使用await的代码中的错误: ~~~ try { version = await lookUpVersion(); } catch (e) { // React to inability to look up the version } ~~~ 你可以在异步函数中多次使用await。例如,以下代码执行了三次await来获取函数的结果。 ~~~ var entrypoint = await findEntrypoint(); var exitCode = await runExecutable(entrypoint, args); await flushThenExit(exitCode); ~~~ 在await表达式中,表达式的值通常是一个Future对象。如果不是,那么这个值将被自动包装成Future。Futrue对象指示返回结果一定是一个对象。表达式的值就是被返回的对象。await表达式会让程序执行挂起,直到返回的对象可用。 ***如果在使用await时出现编译时错误,请确保await在异步函数中*** 。例如,要在应用程序的main()函数中使用wait, main()的主体必须标记为async: ~~~ Future main() async { checkVersion(); print('In main: version is ${await lookUpVersion()}'); } ~~~ ## 声明异步函数 异步函数是函数体被用async修饰符标记的函数。 向函数中添加async关键字将使其返回一个Future。例如,请思考下例中返回一个字符串的同步函数: ~~~ String lookUpVersion() => '1.0.0'; ~~~ 如果你将他改变成一个异步函数,他的返回值将是一个Future: ~~~ Future lookUpVersion() async => '1.0.0'; ~~~ 注意,函数的主体不需要使用Future的API。如果需要,Dart将创建Future的对象。 如果您的函数没有返回一个有用的值,那么将其返回Future\类型。 ## 处理流(Stream) 当您需要从Stream获取值时,您有两个选择: * 使用async和异步的for循环(await for) * 使用Stream API,如[库的引导]中的描述 >注意:在使用await for之前,请确保它使代码更清晰,并且您确实希望等待流(Stream)的所有结果。例如,您通常不应该为UI事件侦听器使用await,因为UI框架会发送无穷无尽的事件流。 > 异步for循环有以下形式: ~~~ await for (varOrType identifier in expression) { // Executes each time the stream emits a value. } ~~~ 表达式的值必须具有Stream类型。执行过程如下: 1. 等待流发出值。 2. 执行for循环的主体,并将变量设置为发出的值。 3. 重复1和2,直到流关闭。 要停止侦听流,您可以使用break或return语句,该语句将跳出for循环,并从流中取消订阅。 如果在实现异步for循环时出现编译时错误,请确保await在异步函数中。例如,要在应用程序的main()函数中使用异步For循环,main()的主体必须标记为async: ~~~ Future main() async { // ... await for (var request in requestServer) { handleRequest(request); } // ... } ~~~ 有关异步编程的更多信息,请参阅[库引导文档]的dart:async部分。还可以参阅文章[Dart语言异步支持:阶段1]和[Dart语言异步支持:阶段2]和[Dart语言规范]。
';