Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "async-await hits beta" blog post #409

Merged
merged 12 commits into from
Sep 30, 2019
160 changes: 160 additions & 0 deletions posts/2019-09-27-Async-await-hits-beta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
layout: post
title: "Async-await hits beta!"
author: Niko Matsakis
---

Big news! As of this writing, **syntactic support for async-await is
available in the Rust beta channel!** It will be available in the 1.39
release, which is expected to be released on **November 7th, 2019**.
Once async-await hits stable, that will mark the culmination of a
**multi-year effort to enable efficient and ergonomic asynchronous I/O
in Rust**. It will not, however, mark the end of the road: there is
still more work to do, both in terms of polish (some of the error
messages we get today are, um, [not great]) and in terms of feature
set ([async fn in traits], anyone?).

[not great]: https://github.com/rust-lang/rust/issues/64130
[async fn in traits]: https://github.com/dtolnay/async-trait

(If you're not familiar with what async-await is, don't despair!
There's a primer and other details later on in this post!)

### Async-await support in the ecosystem growing rapidly

But async-await has never been the entire story. To make good use of
async-await, you also need strong libraries and a vibrant ecosystem.
**Fortunately, you've got a lot of good choices, and they keep getting
better:**

nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
- the async runtime [tokio], for example, recently announced an [alpha
release][] that supports async-await;
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
- the [recently announced][] [async-std][] library was built from the
start on the new async-await syntax;
- using [wasm-bindgen-futures], you can even bridge Rust Futures with
[JavaScript promises];
- finally, in addition to the core runtimes just mentioned,
async-await support is starting to become available in higher-level
[web frameworks][wf] as well.

[wasm-bindgen-futures]: https://docs.rs/crate/wasm-bindgen-futures/0.2.16
[tokio]: https://actix.rs/
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
[actix]: https://actix.rs/
[alpha release]: https://tokio.rs/blog/2019-08-alphas/
[adding support]: https://github.com/actix/actix-web/issues/955#issuecomment-523266936
[async-std]: https://async.rs/
[recently announced]: https://async.rs/blog/announcing-async-std/
[wf]: https://www.arewewebyet.org/topics/frameworks/
[JavaScript promises]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

### Restructuring Async I/O in the Rust org

Now that async-await is stable, we are taking the opportunity to make
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
some changes to our Rust team structure. The current structure
includes two working groups: the [Async Foundations WG], focused on
building up core language support, and the [Async Ecosystem WG],
focused on supporting the ecosystem develop.

**In light of all the activity going on in the ecosystem, however,
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
there it not as much need for the [Async Ecosystem WG], and as such
we've decided to spin it down.** We'll be deprecating the [rustasync
github org]. The [areweasyncyet.rs] and [arewewebyet.org] websites
will move to the main [rust-lang org], but the fate of the other
projects will be decided by the people who built them. A few will
likely be deprecated, and the remainder will be moving out to be
maintained independently.

[areweasyncyet.rs]: https://areweasyncyet.rs/
[arewewebyet.org]: https://www.arewewebyet.org/
[rustasync github org]: https://github.com/rustasync/
[rust-lang org]: https://github.com/rust-lang/
[Async Foundations WG]: https://rust-lang.github.io/compiler-team/working-groups/async-await/
[Async Ecosystem WG]: https://github.com/rustasync/team
[Async Book]: https://github.com/rust-lang/async-book

**The [Async Foundations WG], meanwhile, will continue, but with a
shift in focus.** Now that async-await is en route to stabilization,
the focus will be on polish, such as improving diagnostics, fixing
smaller bugs, and improving documentation such as the [Async
Book]. Once progress is made on that, we'll be considering what
features to implement next.

### Async await: a quick primer

So, what is async await? Async-await is a way to write functions that
can "pause", return control to the runtime, and then pick up from
where they left off. Typically those pauses are to wait for I/O, but
there can be any number of uses.

You may be familiar with the async-await from other languages, such as
JavaScript or C#. Rust's version of the feature is similar, but with a
few key differences.

To use async-await, you start by writing `async fn` instead of `fn`:

```rust
async fn first_function() -> u32 { .. }
```

Unlike a regular function, calling an `async fn` doesn't do anything
to start -- instead, it returns a `Future`. This is a suspended
computation that is waiting to be executed. To actually *execute*
the future, you have to use the `.await` operator:

```rust
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;
...
}
```

This example shows the first difference between Rust and other
languages: we write `future.await` instead of `await future`. This
syntax integrates better with Rust's `?` operator for propagating
errors (which, after all, are very common in I/O). One can simply
write `future.await?` to await the result of a future and propagate
errors. It also has the advantage of making method chaining painless.

### Zero-cost futures

The other difference between Rust futures and futures in other
languages is that they are based on a "poll" model, which makes them
**zero cost**. In other languages, invoking an async function
immediately creates a future and schedules it for execution: awaiting
the future isn't really necessary for it to execute. But this implies
some overhead for each future that is created.

In contrast, in Rust, calling an async function does not do any
scheduling in and of itself, which means that we can compose a complex
nest of futures without incurring a "per-future cost". As an end-user,
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
though, the main thing you'll notice is that **futures feel "lazy"**:
they don't do anything until you await them.

If you'd like a closer look at how futures work under the hood,
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
[withoutboats] gave a [great introduction in this talk][video] from
[Rust LATAM 2019].

[video]: https://www.youtube.com/watch?v=skos4B5x7qE
[Rust LATAM 2019]: https://rustlatam.org/
[withoutboats]: https://rustlatam.org/
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved

### Summary

In summary, if you've an interest in using Async I/O in Rust, this is
a very exciting time! With async-await syntax hitting stable in
November, it's going to be easier than ever to write futures (in
particular, if you tried using the combinator-based futures in the
past, you'll find [async-await integrates much better with Rust's
borrowing system][bc]). Moreover, there are a now a number of great
runtimes and other libraries available in the ecosystem to work with.
So get out there and build stuff!

(Oh, yeah, and please file bugs when you hit confusing or surprising
problems, so we can improve the user experience!)

[bc]: http://aturon.github.io/tech/2018/04/24/async-borrowing/