2.6 KiB
async
/.await
Primer
async
/.await
is Rust's built-in tool for writing asynchronous functions
that look like synchronous code. async
transforms a block of code into a
state machine that implements a trait called Future
. Whereas calling a
blocking function in a synchronous method would block the whole thread,
blocked Future
s will yield control of the thread, allowing other
Future
s to run.
Let's add some dependencies to the Cargo.toml
file:
{{#include ../../examples/01_04_async_await_primer/Cargo.toml:9:10}}
To create an asynchronous function, you can use the async fn
syntax:
async fn do_something() { /* ... */ }
The value returned by async fn
is a Future
. For anything to happen,
the Future
needs to be run on an executor.
{{#include ../../examples/01_04_async_await_primer/src/lib.rs:hello_world}}
Inside an async fn
, you can use .await
to wait for the completion of
another type that implements the Future
trait, such as the output of
another async fn
. Unlike block_on
, .await
doesn't block the current
thread, but instead asynchronously waits for the future to complete, allowing
other tasks to run if the future is currently unable to make progress.
For example, imagine that we have three async fn
: learn_song
, sing_song
,
and dance
:
async fn learn_song() -> Song { /* ... */ }
async fn sing_song(song: Song) { /* ... */ }
async fn dance() { /* ... */ }
One way to do learn, sing, and dance would be to block on each of these individually:
{{#include ../../examples/01_04_async_await_primer/src/lib.rs:block_on_each}}
However, we're not giving the best performance possible this way—we're
only ever doing one thing at once! Clearly we have to learn the song before
we can sing it, but it's possible to dance at the same time as learning and
singing the song. To do this, we can create two separate async fn
which
can be run concurrently:
{{#include ../../examples/01_04_async_await_primer/src/lib.rs:block_on_main}}
In this example, learning the song must happen before singing the song, but
both learning and singing can happen at the same time as dancing. If we used
block_on(learn_song())
rather than learn_song().await
in learn_and_sing
,
the thread wouldn't be able to do anything else while learn_song
was running.
This would make it impossible to dance at the same time. By .await
-ing
the learn_song
future, we allow other tasks to take over the current thread
if learn_song
is blocked. This makes it possible to run multiple futures
to completion concurrently on the same thread.