Dart 库充满了返回 Future 或 Stream 对象 的 函数。这些函数是异步的:它们在设置可能耗时的操作(例如 I/O )后返回,而不等待该操作完成。
async
和 await
关键字支持异步编程,允许你编写看起来类似于同步代码的异步代码。
处理 Futures
当你需要完成的 Future 的结果时,你有两个选择:
- 使用
async
和await
- 使用 Future API , 如库导览中所述
使用 async
和 await
的代码是异步的,但它看起来很像同步代码。例如,这里有一些代码使用 await
来等待异步函数的结果:
1 | await lookUpVersion(); |
要使用 await
,代码必须位于异步函数中 - 标记为 async 的函数:
1 | Future checkVersion() async { |
注意:虽然异步函数可能会执行耗时的操作,但它不会等待这些操作。相反,异步函数只在遇到第一个
await
表达式(详细信息)时才会执行。然后它返回一个 Future 对象,仅在await
表达式完成后才恢复执行。
使用try,catch,最后在使用await的代码中处理错误和清理:
1 | try { |
你可以在异步函数中多次使用 await
。例如,以下代码等待了函数的结果三次:
1 | var entrypoint = await findEntrypoint(); |
在 await
表达式中,表达式的值通常是 Future ;如果不是,那么该值将自动包装在Future中。此 Future 对象表示的是返回一个对象的承诺。 await 表达式的值是返回的对象。 await 表达式使执行暂停,直到该对象可用。
如果在使用 await
时遇到编译时错误,请确保 await
在异步函数中。例如,要在应用程序的 main()
函数中使用 await
,main()
的主体必须标记为 async
:
1 | Future main() 大专栏 (译)异步支持yword">async { |
声明异步函数
异步函数是一个函数,其主体用async修饰符标记。
将 async
关键字添加到函数使其返回一个 Future 。例如,考虑这个同步函数,它返回的是一个 String:
1 | String lookUpVersion() => '1.0.0'; |
如果将其更改为异步函数 - 例如,因为将来的实现将非常耗时 - 返回的值是一个 Future:
1 | Future<String> lookUpVersion() async => '1.0.0'; |
请注意,函数的主体不需要使用Future API。如有必要,Dart会创建 Future
对象。
如果您的函数没有返回有用的值,请使其返回类型为 Future<void>
。
处理 Streams
当你需要从 Stream 获取值时,你有两个选择:
- 使用
async
和一个异步for循环(await for)。 - 使用Stream API,如库导览中所述。
注意:在使用
await for
之前,请确保它使代码更清晰了,并且你确实希望等待所有流的结果。例如,你通常不应该针对UI事件监听器使用await for
,因为UI框架会发送无穷无尽的事件流。
异步for循环具有以下形式:
1 | await for (varOrType identifier in expression) { |
表达式的值必须具有类型化的Stream。执行过程如下:
- 等到流发出一个值。
- 执行for循环的主体,将变量设置为该发出的值。
- 重复1和2,直到关闭流。
要停止监听流,可以使用 break
或 return
语句,该语句会中断 for 循环并从流中取消取消。
如果在实现异步for循环时遇到编译时错误,请确保 await for
是异步函数。例如,要在 app 的main()
函数中使用异步for循环,main()
的主体必须标记为 async
:
1 | Future main() async { |
有关异步编程的更多信息,请参阅库导览的dart:async部分。另请参阅文章Dart语言异步支持:阶段一和Dart语言异步支持:阶段二和Dart语言规范。