重大新闻!截至本文撰写之时,async-await 的语法支持已在 Rust beta 通道中可用!它将在 1.39 版本中提供,该版本预计于 2019 年 11 月 7 日发布。一旦 async-await 进入稳定版,这将标志着为 在 Rust 中实现高效且符合人体工程学的异步 I/O 而进行的多年努力的顶峰。然而,这不会是终点:仍然有更多工作要做,包括在润色方面(我们今天收到的一些错误消息,嗯,不太好)以及在功能集方面(trait 中的 async fn,有人想要吗?)。
(如果您不熟悉 async-await 是什么,请不要绝望!本文稍后会介绍入门知识和其他详细信息!)
生态系统中对 Async-await 的支持正在迅速增长
但是 async-await 从来都不是全部。要充分利用 async-await,您还需要强大的库和充满活力的生态系统。 幸运的是,您有很多不错的选择,而且它们还在不断改进:
- 例如,异步运行时 tokio 最近宣布了一个基于 async-await 的 alpha 版本;
- 最近宣布的 async-std 库从一开始就基于新的 async-await 语法构建;
- 使用 wasm-bindgen-futures,您甚至可以将 Rust Future 与 JavaScript Promise 连接起来;
- hyper 库已 迁移 以采用标准的 Rust Future;
- futures-rs 库的 0.3.0 版本将支持 async-await,并将在 async-await 进入稳定版时发布(您现在可以使用 0.3.0-alpha 版本);
- 最后,async-await 支持也开始在更高级的 Web 框架中提供。
重组 Rust 组织中的异步 I/O
现在 async-await 即将稳定,我们正在借此机会对我们的 Rust 团队结构进行一些更改。当前的结构包括两个工作组:Async Foundations WG,专注于构建核心语言支持,以及 Async Ecosystem WG,专注于支持生态系统的发展。
鉴于生态系统中正在进行的所有活动,对 Async Ecosystem WG 的需求并不那么大,因此我们决定将其解散。 我们将弃用 rustasync github 组织。areweasyncyet.rs 和 arewewebyet.org 网站将移至主要的 rust-lang 组织,但其他项目的命运将由构建它们的人员决定。一些项目可能会被弃用,其余项目将移出以进行独立维护。
与此同时,Async Foundations WG 将继续存在,但重点将转移。 既然 async-await 正在走向稳定,重点将放在润色上,例如改进诊断、修复较小的错误以及改进文档,例如 async book。一旦在这方面取得进展,我们将考虑接下来要实现的功能。
(顺便说一句:这是我们第一次选择解散一个工作组,我们意识到我们没有为此制定正式的政策。我们已经与 治理工作组 创建了一个 issue,以便将来对此进行研究。)
Async await:快速入门
那么,async await 是什么?Async-await 是一种编写可以“暂停”、将控制权返回给运行时,然后从中断处继续执行的函数的方法。通常,这些暂停是为了等待 I/O,但可以有许多用途。
您可能熟悉其他语言(例如 JavaScript 或 C#)中的 async-await。Rust 版本的该功能类似,但有一些关键差异。
要使用 async-await,您首先要编写 async fn
而不是 fn
async fn first_function() -> u32 { .. }
与常规函数不同,调用 async fn
不会启动任何操作 -- 相反,它会返回一个 Future
。这是一个等待执行的挂起计算。要真正执行 future,您必须使用 .await
运算符
async fn another_function() {
// Create the future:
let future = first_function();
// Await the future, which will execute it (and suspend
// this function if we encounter a need to wait for I/O):
let result: u32 = future.await;
...
}
此示例显示了 Rust 与其他语言之间的第一个区别:我们编写 future.await
而不是 await future
。此语法更好地与 Rust 的 ?
运算符集成,用于传播错误(毕竟,这在 I/O 中非常常见)。可以简单地编写 future.await?
来等待 future 的结果并传播错误。它还具有使方法链接变得轻松的优点。
零成本 Future
Rust future 和其他语言中的 future 之间的另一个区别是,它们基于“轮询”模型,这使它们成为零成本。在其他语言中,调用异步函数会立即创建一个 future 并将其调度以执行:等待 future 对于执行来说并不是真正必要的。但这意味着为创建的每个 future 都会有一些开销。
相比之下,在 Rust 中,调用异步函数本身不会进行任何调度,这意味着我们可以组成一个复杂的 future 嵌套,而不会产生每个 future 的开销。但是,作为最终用户,您会注意到的主要事情是future 感觉“懒惰”:在您等待它们之前,它们不会执行任何操作。
如果您想更深入地了解 future 的工作原理,请查看 async book 的执行器部分,或者观看 withoutboats 在 Rust LATAM 2019 上就此主题进行的 精彩演讲。
总结
总而言之,如果您有兴趣在 Rust 中使用异步 I/O,那么这是一个非常激动人心的时刻!随着 async-await 语法在 11 月进入稳定版,编写 future 将比以往任何时候都更容易(特别是,如果您过去尝试使用基于组合器的 future,您会发现 async-await 与 Rust 的借用系统集成得更好)。此外,现在生态系统中有很多很棒的运行时和其他库可供使用。所以,走出去,构建东西吧!
(哦,对了,当您遇到令人困惑或意外的问题时,请提交错误报告,以便我们可以改善用户体验!)