Rust supports many different models of concurrency including the "async" model popularized by the node ecosystem. It allows us to express how operations could be asynchronous in terms of potential pausing points and eventual results.
use trpl::Html;
fn main() {
let args: Vec<String> = std::env::args().collect();
trpl::block_on(async {
let url = &args[1];
match page_title(url).await {
Some(title) => println!("{url}: {title}"),
None => println!("{url}: no title found"),
}
})
}
async fn page_title(url: &str) -> Option<String> {
let resp = trpl::get(url).await;
let resp_text = resp.text().await;
Html::parse(&resp_text)
.select_first("title")
.map(|title| title.inner_html())
}
Say for example we need to download many files. The simple approach to avoid blocking our main thread by spawning a dedicated thread to download each file. However, the overhead of the system resources used by those threads could eventually become a problem. We can instead use rust's async features to define a number of tasks and allow the runtime to choose the best order and manner in which to run them.
futures and async syntax
A future is a value that may not be ready now, but will become ready at some
point in the future. In rust futures are types that implement the Future
trait.
You can apply the aync keyword to a function or block to specify that they can
be interrupted and resumed. Within an async block, you can use the await
keyword to await a future. This is a potential spot for the program's
execution to pause and periodically check if the future is resolved.
async main?
Most languages that support async bundle a runtime, but Rust does not. Instead, there are many different async runtimes available, each of which makes different tradeoffs suitable to the use case it targets.
As a result main can’t be simply marked async. The code needs a runtime: a Rust
crate that manages the details of executing asynchronous code. This is usually
done by creating a block in your main function and calling a function from your
runtime like tokio::block_on.
Some runtimes will include a macro allowing you to write async main which the
macro will then transform into a normal main function with a block that calls
the runtime.