toiti
toiti

Reputation: 41

How to run another function as async in rust?

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

Answers (1)

rodrigo
rodrigo

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

Related Questions