Reputation: 41
as a JS dev i'm having a real hard time understanding error handling in rust. especially with asyncronisity. heres some code from another stackoverflow question using async-std
to call an async scraper function:
use std::fs::File;
use std::io::{self, BufReader};
use std::io::BufRead;
//use async_std::task;
async fn scrape<R: BufRead>(reader: &mut R) -> io::Result<()> {
reader.lines()
.try_for_each(|line_result| line_result.and_then(|line| Ok(println!("{}", line))))?;
Ok(())
}
fn main() {
let file_result = File::open("wlist.txt");
let file;
match file_result {
Ok(f) => file = f,
Err(e) => { println!("File open error! {}", e); return; },
}
let mut reader = BufReader::new(file);
match scrape(&mut reader) {
Ok(_) => println!("done!"),
Err(e) => println!("File read error! {}", e),
}
}
I'm trying to call scrape
in an asyncronous way like:
task::block_on(match scrape(&mut reader) {
Ok(_) => println!("done!"),
Err(e) => println!("File read error! {}", e),
})
but it errors with
the trait std::future::Future is not implemented for ()
What's wrong with the code snippet? how can I run scraper as async with as less modification to the rest of the code as possible?
Upvotes: 3
Views: 3131
Reputation: 98516
Usually you can only call async functions from async context, except when you use the block_on
or spawn
functions or similar from your executor.
The easiest way to create an async context is an async
block. Then you need to use the .await
operator to properly chain asyncs:
task::block_on(async {
match scrape(&mut reader).await {
Ok(_) => println!("done!"),
Err(e) => println!("File read error! {}", e),
}
})
For more complex code you will have an async function that may fail that calls another async function that also may fail. In those cases it is idiomatic to write other_async_func().await?
to await and forward the error at the same time.
Upvotes: 2