|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Async-await hits beta!" |
| 4 | +author: Niko Matsakis |
| 5 | +--- |
| 6 | + |
| 7 | +Big news! As of this writing, **syntactic support for async-await is |
| 8 | +available in the Rust beta channel!** It will be available in the 1.39 |
| 9 | +release, which is expected to be released on **November 7th, 2019**. |
| 10 | +Once async-await hits stable, that will mark the culmination of a |
| 11 | +**multi-year effort to enable efficient and ergonomic asynchronous I/O |
| 12 | +in Rust**. It will not, however, mark the end of the road: there is |
| 13 | +still more work to do, both in terms of polish (some of the error |
| 14 | +messages we get today are, um, [not great]) and in terms of feature |
| 15 | +set ([async fn in traits], anyone?). |
| 16 | + |
| 17 | +[not great]: https://github.com/rust-lang/rust/issues/64130 |
| 18 | +[async fn in traits]: https://github.com/dtolnay/async-trait |
| 19 | + |
| 20 | +(If you're not familiar with what async-await is, don't despair! |
| 21 | +There's a primer and other details later on in this post!) |
| 22 | + |
| 23 | +### Async-await support in the ecosystem growing rapidly |
| 24 | + |
| 25 | +But async-await has never been the entire story. To make good use of |
| 26 | +async-await, you also need strong libraries and a vibrant ecosystem. |
| 27 | +**Fortunately, you've got a lot of good choices, and they keep getting |
| 28 | +better:** |
| 29 | + |
| 30 | +- the async runtime [tokio], for example, recently announced an [alpha |
| 31 | + release][] based on async-await; |
| 32 | +- the [recently announced][] [async-std][] library was built from the |
| 33 | + start on the new async-await syntax; |
| 34 | +- using [wasm-bindgen-futures], you can even bridge Rust Futures with |
| 35 | + [JavaScript promises]; |
| 36 | +- the [hyper library][hyper] has [migrated][hyper#1805] to adopt standard Rust futures; |
| 37 | +- the 0.3.0 version of the [futures-rs library][futures] will support |
| 38 | + async-await and will be released by the time async-await hits stable |
| 39 | + (you can use the [0.3.0-alpha][] releases now); |
| 40 | +- finally, async-await support is starting to become available in higher-level |
| 41 | + [web frameworks][wf] as well. |
| 42 | + |
| 43 | +[futures]: https://crates.io/crates/futures-preview |
| 44 | +[0.3.0-alpha]: https://rust-lang-nursery.github.io/futures-rs/blog/2018/07/19/futures-0.3.0-alpha.1.html |
| 45 | +[wasm-bindgen-futures]: https://docs.rs/crate/wasm-bindgen-futures/0.2.16 |
| 46 | +[tokio]: https://tokio.rs/ |
| 47 | +[actix]: https://actix.rs/ |
| 48 | +[alpha release]: https://tokio.rs/blog/2019-08-alphas/ |
| 49 | +[adding support]: https://github.com/actix/actix-web/issues/955#issuecomment-523266936 |
| 50 | +[async-std]: https://async.rs/ |
| 51 | +[recently announced]: https://async.rs/blog/announcing-async-std/ |
| 52 | +[wf]: https://www.arewewebyet.org/topics/frameworks/ |
| 53 | +[JavaScript promises]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises |
| 54 | +[hyper]: https://hyper.rs |
| 55 | +[hyper#1805]: https://github.com/hyperium/hyper/issues/1805 |
| 56 | + |
| 57 | +### Restructuring Async I/O in the Rust org |
| 58 | + |
| 59 | +Now that async-await is approaching stable, we are taking the |
| 60 | +opportunity to make some changes to our Rust team structure. The |
| 61 | +current structure includes two working groups: the [Async Foundations |
| 62 | +WG], focused on building up core language support, and the [Async |
| 63 | +Ecosystem WG], focused on supporting the ecosystem develop. |
| 64 | + |
| 65 | +**In light of all the activity going on in the ecosystem, however, |
| 66 | +there it not as much need for the [Async Ecosystem WG], and as such |
| 67 | +we've decided to spin it down.** We'll be deprecating the [rustasync |
| 68 | +github org]. The [areweasyncyet.rs] and [arewewebyet.org] websites |
| 69 | +will move to the main [rust-lang org], but the fate of the other |
| 70 | +projects will be decided by the people who built them. A few will |
| 71 | +likely be deprecated, and the remainder will be moving out to be |
| 72 | +maintained independently. |
| 73 | + |
| 74 | +[areweasyncyet.rs]: https://areweasyncyet.rs/ |
| 75 | +[arewewebyet.org]: https://www.arewewebyet.org/ |
| 76 | +[rustasync github org]: https://github.com/rustasync/ |
| 77 | +[rust-lang org]: https://github.com/rust-lang/ |
| 78 | +[Async Foundations WG]: https://rust-lang.github.io/compiler-team/working-groups/async-await/ |
| 79 | +[Async Ecosystem WG]: https://github.com/rustasync/team |
| 80 | +[async book]: https://github.com/rust-lang/async-book |
| 81 | + |
| 82 | +**The [Async Foundations WG], meanwhile, will continue, but with a |
| 83 | +shift in focus.** Now that async-await is en route to stabilization, |
| 84 | +the focus will be on polish, such as improving diagnostics, fixing |
| 85 | +smaller bugs, and improving documentation such as the [async |
| 86 | +book]. Once progress is made on that, we'll be considering what |
| 87 | +features to implement next. |
| 88 | + |
| 89 | +(An aside: this is the first time that we've ever opted to spin *down* |
| 90 | +a working group, and we realized that we don't have a formal policy |
| 91 | +for that. We've [created an issue][gov25] with the [governance working |
| 92 | +group][gov-wg] to look into that for the future.) |
| 93 | + |
| 94 | +[gov25]: https://github.com/rust-lang/wg-governance/issues/25 |
| 95 | +[gov-wg]: https://github.com/rust-lang/wg-governance/ |
| 96 | + |
| 97 | +### Async await: a quick primer |
| 98 | + |
| 99 | +So, what is async await? Async-await is a way to write functions that |
| 100 | +can "pause", return control to the runtime, and then pick up from |
| 101 | +where they left off. Typically those pauses are to wait for I/O, but |
| 102 | +there can be any number of uses. |
| 103 | + |
| 104 | +You may be familiar with the async-await from other languages, such as |
| 105 | +JavaScript or C#. Rust's version of the feature is similar, but with a |
| 106 | +few key differences. |
| 107 | + |
| 108 | +To use async-await, you start by writing `async fn` instead of `fn`: |
| 109 | + |
| 110 | +```rust |
| 111 | +async fn first_function() -> u32 { .. } |
| 112 | +``` |
| 113 | + |
| 114 | +Unlike a regular function, calling an `async fn` doesn't do anything |
| 115 | +to start -- instead, it returns a `Future`. This is a suspended |
| 116 | +computation that is waiting to be executed. To actually *execute* |
| 117 | +the future, you have to use the `.await` operator: |
| 118 | + |
| 119 | +```rust |
| 120 | +async fn another_function() { |
| 121 | + // Create the future: |
| 122 | + let future = first_function(); |
| 123 | + |
| 124 | + // Await the future, which will execute it (and suspend |
| 125 | + // this function if we encounter a need to wait for I/O): |
| 126 | + let result: u32 = future.await; |
| 127 | + ... |
| 128 | +} |
| 129 | +``` |
| 130 | + |
| 131 | +This example shows the first difference between Rust and other |
| 132 | +languages: we write `future.await` instead of `await future`. This |
| 133 | +syntax integrates better with Rust's `?` operator for propagating |
| 134 | +errors (which, after all, are very common in I/O). One can simply |
| 135 | +write `future.await?` to await the result of a future and propagate |
| 136 | +errors. It also has the advantage of making method chaining painless. |
| 137 | + |
| 138 | +### Zero-cost futures |
| 139 | + |
| 140 | +The other difference between Rust futures and futures in other |
| 141 | +languages is that they are based on a "poll" model, which makes them |
| 142 | +**zero cost**. In other languages, invoking an async function |
| 143 | +immediately creates a future and schedules it for execution: awaiting |
| 144 | +the future isn't really necessary for it to execute. But this implies |
| 145 | +some overhead for each future that is created. |
| 146 | + |
| 147 | +In contrast, in Rust, calling an async function does not do any |
| 148 | +scheduling in and of itself, which means that we can compose a complex |
| 149 | +nest of futures without incurring a per-future cost. As an end-user, |
| 150 | +though, the main thing you'll notice is that **futures feel "lazy"**: |
| 151 | +they don't do anything until you await them. |
| 152 | + |
| 153 | +If you'd like a closer look at how futures work under the hood, take a |
| 154 | +look at [the executor section] of the [async book], or watch the |
| 155 | +[excellent talk][video] that [withoutboats] gave at [Rust LATAM 2019] |
| 156 | +on the topic. |
| 157 | + |
| 158 | +[the executor section]: https://rust-lang.github.io/async-book/02_execution/04_executor.html |
| 159 | +[video]: https://www.youtube.com/watch?v=skos4B5x7qE |
| 160 | +[Rust LATAM 2019]: https://rustlatam.org/ |
| 161 | +[withoutboats]: https://github.com/withoutboats |
| 162 | + |
| 163 | +### Summary |
| 164 | + |
| 165 | +In summary, if you've an interest in using Async I/O in Rust, this is |
| 166 | +a very exciting time! With async-await syntax hitting stable in |
| 167 | +November, it's going to be easier than ever to write futures (in |
| 168 | +particular, if you tried using the combinator-based futures in the |
| 169 | +past, you'll find [async-await integrates much better with Rust's |
| 170 | +borrowing system][bc]). Moreover, there are a now a number of great |
| 171 | +runtimes and other libraries available in the ecosystem to work with. |
| 172 | +So get out there and build stuff! |
| 173 | + |
| 174 | +(Oh, yeah, and please file bugs when you hit confusing or surprising |
| 175 | +problems, so we can improve the user experience!) |
| 176 | + |
| 177 | +[bc]: http://aturon.github.io/tech/2018/04/24/async-borrowing/ |
0 commit comments