47·异步编程进阶

async/await 基础

async/await 基础

学习目标

  1. 理解异步编程模型
  2. 掌握 async fn.await
  3. 理解 Future 的概念

核心概念

async fn

async fn greet() -> String {
    String::from("hello")
}

// 等价于
fn greet() -> impl std::future::Future<Output = String> {
    async { String::from("hello") }
}

.await

async fn fetch_data() -> String {
    // 模拟异步操作
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    String::from("data")
}

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

Future trait

trait Future {
    type Output;
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

enum Poll<T> {
    Ready(T),    // 完成
    Pending,     // 未完成,稍后再试
}

并发执行

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

async fn task(id: u32) -> String {
    sleep(Duration::from_millis(100)).await;
    format!("任务 {} 完成", id)
}

#[tokio::main]
async fn main() {
    // 串行
    let r1 = task(1).await;
    let r2 = task(2).await;

    // 并发
    let (r1, r2) = tokio::join!(task(1), task(2));

    // 动态并发
    let mut handles = vec![];
    for i in 0..5 {
        handles.push(tokio::spawn(task(i)));
    }
    for handle in handles {
        let result = handle.await.unwrap();
        println!("{}", result);
    }
}

async 块

#[tokio::main]
async fn main() {
    let future = async {
        println!("执行中...");
        42
    };

    let result = future.await;
    println!("结果: {}", result);
}

tokio::spawn

#[tokio::main]
async fn main() {
    let handle = tokio::spawn(async {
        // 后台任务
        "result"
    });

    // 做其他事情...

    let result = handle.await.unwrap();
    println!("{}", result);
}

实践练习

练习 1:并发请求

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

async fn fetch_user(id: u32) -> String {
    sleep(Duration::from_millis(100)).await;
    format!("User-{}", id)
}

#[tokio::main]
async fn main() {
    let users: Vec<String> = (1..=5)
        .map(|id| fetch_user(id))
        .collect::<Vec<_>>()
        .await
        .into_iter()
        .collect();

    println!("{:?}", users);
}

常见错误

1. 忘记 .await

async fn foo() -> i32 { 42 }

#[tokio::main]
async fn main() {
    let f = foo();      // 这是 Future,不是值
    let v = foo().await; // ✅ 这才是 i32
}

2. 在同步代码中使用 async

// ❌ 不能在同步函数中 .await
// fn main() {
//     foo().await;
// }

// ✅ 需要异步运行时
#[tokio::main]
async fn main() {
    foo().await;
}

小结

概念说明
async fn异步函数,返回 Future
.await等待 Future 完成
tokio::spawn并发执行任务
tokio::join!并发等待多个 Future
Future惰性计算,需要执行器驱动

练习编辑器

rust
Loading...