JSTAcademy
0 XP
Dashboard
Crash Courses
Async with Tokio
45 min
PhD+195 XP
Crash Courses · PhD

Async with Tokio

Non-blocking I/O, async/await, and the Tokio runtime
45 min read+195 XP on completionCert: Rust Crash Course
Tap any word in the text below to start reading from there.

Async with Tokio

Setup

Add to Cargo.toml:

[dependencies]
tokio  = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
serde  = { version = "1", features = ["derive"] }

Basic async/await

use tokio::time::{sleep, Duration};

async fn fetch_data(id: u32) -> String {
    sleep(Duration::from_millis(100)).await; // simulate I/O
    format!("Data for id={}", id)
}

#[tokio::main]
async fn main() {
    let result = fetch_data(42).await;
    println!("{}", result);
}

Concurrent Tasks with tokio::spawn

use tokio::task::JoinHandle;

#[tokio::main]
async fn main() {
    let mut handles: Vec<JoinHandle<String>> = Vec::new();

    for i in 0..5 {
        let h = tokio::spawn(async move {
            tokio::time::sleep(Duration::from_millis(50)).await;
            format!("Task {} done", i)
        });
        handles.push(h);
    }

    for h in handles {
        let result = h.await.unwrap();
        println!("{}", result);
    }
}

All 5 tasks run concurrently — total time ~50ms, not 250ms.

HTTP Request with reqwest

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Post {
    id:     u32,
    title:  String,
    body:   String,
    userId: u32,
}

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let post: Post = reqwest::get("https://jsonplaceholder.typicode.com/posts/1")
        .await?
        .json::<Post>()
        .await?;

    println!("Title: {}", post.title);
    Ok(())
}

tokio::join! — Wait for Multiple Futures

async fn task_a() -> &'static str { "A" }
async fn task_b() -> &'static str { "B" }

#[tokio::main]
async fn main() {
    let (a, b) = tokio::join!(task_a(), task_b());
    println!("{} {}", a, b); // both run concurrently
}

Async Channels

use tokio::sync::mpsc;

#[tokio::main]
async fn main() {
    let (tx, mut rx) = mpsc::channel::<u32>(32);

    tokio::spawn(async move {
        for i in 0..5 {
            tx.send(i).await.unwrap();
        }
    });

    while let Some(val) = rx.recv().await {
        println!("Received: {}", val);
    }
}
0%