⚠️ PLACEHOLDER CONTENT: This is a fake blog post with dummy content for demonstration purposes only.
Introduction#
Rust’s async/await syntax makes writing asynchronous code feel almost synchronous. Here’s a quick look at how it works.
Basic Example#
use tokio::time::{sleep, Duration};
async fn fetch_data(id: u32) -> String {
// Simulate network delay
sleep(Duration::from_millis(100)).await;
format!("Data for item {}", id)
}
#[tokio::main]
async fn main() {
let result = fetch_data(42).await;
println!("{}", result);
}
Spawning Concurrent Tasks#
You can run multiple futures concurrently with tokio::join!:
⚠️ PLACEHOLDER CONTENT: This is a fake blog post with dummy content for demonstration purposes only.
The Problem#
Managing state in Flutter can get messy. Here are some patterns that help.
Using ValueNotifier#
A simple approach for local state:
class CounterWidget extends StatefulWidget {
const CounterWidget({super.key});
@override
State<CounterWidget> createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
final _counter = ValueNotifier<int>(0);
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<int>(
valueListenable: _counter,
builder: (context, value, child) {
return Text('Count: $value');
},
);
}
void increment() => _counter.value++;
}
Extension Methods#
Dart extension methods can clean up your code:
⚠️ PLACEHOLDER CONTENT: This is a fake blog post with dummy content for demonstration purposes only.
The ? Operator#
Rust’s ? operator makes error propagation elegant:
use std::fs::File;
use std::io::{self, Read};
fn read_config() -> io::Result<String> {
let mut file = File::open("config.toml")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
Custom Error Types#
Define your own errors with thiserror:
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AppError {
#[error("Configuration file not found")]
ConfigNotFound,
#[error("Invalid data: {0}")]
InvalidData(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
fn load_config() -> Result<Config, AppError> {
let data = std::fs::read_to_string("config.toml")
.map_err(|_| AppError::ConfigNotFound)?;
parse_config(&data)
.ok_or_else(|| AppError::InvalidData("malformed TOML".into()))
}
The anyhow Crate#
For applications (not libraries), anyhow simplifies everything: