Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Async พื้นฐาน

Asynchronous programming ใน Rust ช่วยจัดการ I/O-bound tasks อย่างมีประสิทธิภาพ

⚡ Async vs Sync Visualization

Async State Machine Diagram

Sync vs Async

Synchronous (Blocking)

fn main() {
    let data1 = fetch_data_1(); // รอ... 2 seconds
    let data2 = fetch_data_2(); // รอ... 2 seconds
    // Total: 4 seconds
}

Asynchronous (Non-blocking)

async fn main() {
    let (data1, data2) = join!(
        fetch_data_1(), // เริ่มพร้อมกัน
        fetch_data_2()
    );
    // Total: ~2 seconds
}

async fn

async fn hello_world() {
    println!("Hello, world!");
}

// async fn returns a Future
// must be run by an executor

async fn returns impl Future - ไม่รันทันที ต้อง await หรือใช้ executor


.await

async fn fetch_number() -> i32 {
    // simulate async work
    42
}

async fn main() {
    let number = fetch_number().await; // รอ Future complete
    println!("Number: {}", number);
}

Sequential vs Concurrent

async fn learn_song() -> String {
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    "La la la".to_string()
}

async fn sing_song(song: &str) {
    println!("Singing: {}", song);
}

async fn dance() {
    tokio::time::sleep(std::time::Duration::from_secs(1)).await;
    println!("Dancing!");
}

// Sequential
async fn sequential() {
    let song = learn_song().await; // 1 sec
    sing_song(&song).await;
    dance().await;                  // 1 sec
    // Total: 2+ seconds
}

// Concurrent - dance while learning
async fn concurrent() {
    let (song, _) = tokio::join!(
        learn_song(),  // start learning
        dance()        // dance at the same time
    );
    sing_song(&song).await;
    // Total: ~1 second (overlapped)
}

Runtime: Tokio

Rust ไม่มี async runtime ในตัว ต้องใช้ library:

# Cargo.toml
[dependencies]
tokio = { version = "1", features = ["full"] }

Basic Usage

#[tokio::main]
async fn main() {
    println!("Hello from async main!");

    let result = do_something().await;
    println!("Result: {}", result);
}

async fn do_something() -> i32 {
    // simulate async work
    tokio::time::sleep(std::time::Duration::from_millis(100)).await;
    42
}

Manual Runtime

fn main() {
    let rt = tokio::runtime::Runtime::new().unwrap();

    rt.block_on(async {
        println!("Running on tokio runtime");
    });
}

async Block

async fn example() {
    let future = async {
        // code here runs lazily
        println!("Inside async block");
        42
    };

    // future ยังไม่รัน!
    let result = future.await;
    println!("Result: {}", result);
}

Capture Variables

async fn example() {
    let name = String::from("Alice");

    // move ownership into async block
    let greeting = async move {
        format!("Hello, {}!", name)
    };

    // name moved, can't use here
    // println!("{}", name); // ❌

    println!("{}", greeting.await);
}

Futures are Lazy

async fn my_async_fn() {
    println!("This runs when awaited");
}

fn main() {
    let future = my_async_fn(); // ไม่รันอะไรเลย!

    // ต้อง await หรือใช้ executor
    // future.await; // or
    // tokio::runtime::Runtime::new().unwrap().block_on(future);
}

Return Types

use std::future::Future;

// These are equivalent:
async fn foo() -> i32 {
    42
}

fn bar() -> impl Future<Output = i32> {
    async {
        42
    }
}

Error Handling in Async

async fn fetch_data() -> Result<String, std::io::Error> {
    // simulate possible failure
    Ok("data".to_string())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let data = fetch_data().await?;
    println!("Data: {}", data);
    Ok(())
}

Async in Traits (Rust 1.75+)

trait AsyncFetcher {
    async fn fetch(&self) -> String;
}

struct MyFetcher;

impl AsyncFetcher for MyFetcher {
    async fn fetch(&self) -> String {
        "data".to_string()
    }
}

When to Use Async

SituationUse
I/O-bound (network, files)✅ Async
CPU-bound (computation)❌ Use threads
Need simple code❌ Stick with sync
High concurrency✅ Async

ลองทำดู! 🎯

  1. สร้าง async function ที่ return Result
  2. ใช้ tokio::time::sleep แล้ว await
  3. ลอง tokio::join! กับ 2 futures

สรุป

ConceptDescription
async fnReturns Future
.awaitWait for Future
async { }Async block
#[tokio::main]Async main entry
LazyFutures don’t run until awaited

Runtimes

RuntimeUse Case
TokioGeneral purpose, most popular
async-stdSimpler, std-like API
smolMinimal, lightweight

👉 ต่อไป: Futures