如何在 Rust 中将另一个函数作为异步函数运行?

3

作为一个 JS 开发者,我在理解 Rust 中的错误处理方面遇到了很大的困难,特别是涉及到异步处理时。以下是来自 StackOverflow 上另一个问题的代码示例,使用 async-std 调用一个异步爬虫函数:

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),
    }
}

我想以异步的方式调用scrape,例如:
    task::block_on(match scrape(&mut reader) {
        Ok(_) => println!("done!"),
        Err(e) => println!("File read error! {}", e),
    })

但是它出现了错误,错误信息为未为()实现std::future::Future特性

这段代码有什么问题?如何尽可能少地修改其余代码,使爬虫运行为异步?

1个回答

2
通常情况下,您只能在异步上下文中调用异步函数,除非您使用block_onspawn等来自执行器的类似函数。
创建异步上下文最简单的方法是使用async块。然后,您需要使用.await运算符正确链接异步操作:
    task::block_on(async {
        match scrape(&mut reader).await {
            Ok(_) => println!("done!"),
            Err(e) => println!("File read error! {}", e),
        }
    })

对于更复杂的代码,您将拥有一个可能失败的异步函数,该函数调用另一个也可能失败的异步函数。在这些情况下,惯用的写法是编写 other_async_func().await? 来同时等待和转发错误。


错误[E0277]: 未满足std::result::Result<(), std::io::Error>: std::future::Future的特质限制 --> src\main.rs:22:15 | 22 | match scrape(&mut reader).await { | ^^^^^^^^^^^^^^^^^^^^^^^^^ std::result::Result<(), std::io::Error>未实现std::future::Future的特质。 - toiti
这意味着你正在使用.await,但它不是一个“Future”,很可能是因为你从async fn scrape(...)中删除了async。要么在函数中添加async,要么在调用中删除.await。自然地,由于你的代码没有任何异步I/O操作,实践中不会有什么影响。 - rodrigo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接