When a program waits for a server to respond, ordinary code blocks its thread. Async Rust lets other work proceed during that wait. An `async fn` creates a future: a computation whose result may be available now or later. Its declared return type looks ordinary, but calling `async fn give_8() -> u8` gives you an `impl Future<Output = u8>`, not a `u8` yet. section 19.3 section 19.3.1
Add `.await` to obtain the future’s output. You can use `.await` only inside an async function or block. A runtime handles checking whether the future is ready; you do not need to call `poll` yourself. If it is pending, the runtime can return to it later. Don’t worry about the deeper details of `Pin` to get started. section 19.3.1 section 19.3.2
Await a value in main
```rust async fn give_8() -> u8 { 8 } #[tokio::main] async fn main() { let number = give_8().await; println!("{number}"); } ``` Trying `.await` in a regular `main` produces a compiler error; changing it to `async fn main` alone produces another. `#[tokio::main]` supplies the Tokio runtime that runs the async body to completion. section 19.3.2 section 19.3.3
A few practical consequences follow:
- A regular function cannot await an async function, so a caller that needs its result may need to become async too. An async function can call a regular function, but that call can still block the thread. section 19.3.3
- Awaiting several futures one after another finishes each before starting the next. Tokio’s `join!` polls them together; `select!` takes the first completion, and `try_join!` handles futures that return results. section 19.3.4 section 19.4
- With reqwest’s async client, await both sending a request and reading the response text. An Axum route can use an async handler, and its server’s `.serve()` call is awaited. section 19.3.3 section 24.1.1
use rand::*;
use tokio::join;
use std::time::Duration;
async fn wait_and_give_u8(num: u8) -> u8 {
let mut rng = rand::thread_rng();
let wait_time = rng.gen_range(1..100);
tokio::time::sleep(Duration::from_millis(wait_time)).await;
println!("Got a number! {num}");
num
}
#[tokio::main]
async fn main() {
let nums = join!(
wait_and_give_u8(1),
wait_and_give_u8(2),
wait_and_give_u8(3)
);
println!("{nums:?}");
}
Three futures each take a short, randomly timed nonblocking sleep. `join!` polls them together, so their completion messages may appear in a different order even though the returned tuple stays ordered. section 19.3.4
















