Programación asíncrona en Rust: guía completa con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Programación asíncrona en Rust: desde lo básico hasta técnicas avanzadas



Las aplicaciones modernas requieren alto rendimiento y trabajo eficiente con operaciones de I/O. Rust, conocido por su velocidad y seguridad, ofrece un potente modelo de programación asíncrona. En esta guía, analizaremos en detalle cómo usar async/await, la biblioteca tokio y otras herramientas para crear programas asíncronos rápidos y confiables.



¿Qué es la programación asíncrona en Rust?



La programación asíncrona es un paradigma que permite ejecutar múltiples tareas simultáneamente sin crear hilos del SO. En lugar de bloquear un hilo mientras se espera una operación de I/O (lectura de archivo, solicitud HTTP), una función asíncrona se "suspende" y cede el control a otras tareas. Rust implementa esto a través de Futures y el mecanismo async/await.



Conceptos clave:

  • Future — un trait que representa una operación asíncrona que puede completarse más tarde.
  • async/await — azúcar sintáctico para trabajar con Futures.
  • Runtime (ejecutor) — el entorno de ejecución que sondea los Futures y los ejecuta. El más popular es Tokio.
  • Task — una unidad de trabajo ligera, gestionada por el Runtime.


Primer programa asíncrono en Rust



Para empezar, agregue las dependencias en Cargo.toml:



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


Ahora escribamos un cliente HTTP asíncrono simple:



use reqwest;use serde::Deserialize;

#[derive(Deserialize, Debug)]struct Todo { userId: u32, id: u32, title: String, completed: bool,}

#[tokio::main]async fn main() -> Result<(), Box> { // Solicitud GET asíncrona let response = reqwest::get("https://jsonplaceholder.typicode.com/todos/1") .await?; // await suspende la ejecución hasta que llegue la respuesta let todo: Todo = response.json().await?; // Deserialización asíncrona println!("Tarea obtenida: {:#?}", todo); Ok(())}


Observe la macro #[tokio::main] — convierte la función main normal en un punto de entrada asíncrono, iniciando el Runtime de Tokio.



Creación de funciones asíncronas y trabajo con tareas



Puede crear sus propias funciones asíncronas usando la palabra clave async fn:



use std::time::Duration;use tokio::time::sleep;

async fn simulate_work(id: u32, duration_secs: u64) -> String { println!("Tarea {} iniciada", id); sleep(Duration::from_secs(duration_secs)).await; // Retardo asíncrono println!("Tarea {} completada", id); format!("Resultado de la tarea {}", id)}

#[tokio::main]async fn main() { let start = std::time::Instant::now(); // Creamos tareas asíncronas (tasks) let task1 = tokio::spawn(simulate_work(1, 2)); let task2 = tokio::spawn(simulate_work(2, 1)); let task3 = tokio::spawn(simulate_work(3, 3)); // Esperamos la finalización de todas las tareas let results = tokio::join!(task1, task2, task3); // Procesamos los resultados for result in &results { match result { Ok(msg) => println!("{}", msg), Err(e) => eprintln!("Error: {}", e), } } println!("Tiempo total: {:?}", start.elapsed()); // Se ejecutará en ~3 segundos, ¡no en 6!}


La función tokio::spawn crea una tarea asíncrona independiente que se ejecuta en paralelo con otras. tokio::join! espera la finalización de todos los futures pasados.



Técnicas avanzadas

Blogs

Book Recommendations