Rust - 如何在一个应用程序中使用同步和异步包

问题描述

我开始使用 Druid crate 和 Crabler crate 编写一个程序,以制作我可以探索其数据的网络抓取应用程序。在我花了一段时间构建这个程序很久之后,我才意识到合并同步和异步编程是一个坏主意。我现在想要做的是在应用程序打开时(最好每小时运行一次)。

现在,直到应用程序关闭后,scraper 才会运行。我尝试使用 Tokio 的 spawn 来创建一个在应用程序打开之前启动的单独线程,但这不起作用,因为 Crabler 未来没有“发送”特征。

我尝试制作一个最小的功能程序,如下所示。 title_handler 未按预期运行,但在其他方面表明我遇到了问题。

是否可以允许 WebScraper 在应用程序打开时运行?如果是这样,如何?

编辑:我尝试使用 task::spawn_blocking() 运行应用程序,但它抛出了大量错误包括德鲁伊没有实现 Send 特性。

use crabler::*;
use druid::widget::prelude::*;
use druid::widget::{Align,Flex,Label,TextBox};
use druid::{AppLauncher,Data,Lens,WindowDesc,WidgetExt};

const ENTRY_PREFIX: [&str; 1] = ["https://duckduckgo.com/?t=ffab&q=rust&ia=web"];

// Use WebScraper trait to get each item with the ".result__title" class
#[derive(WebScraper)]
#[on_response(response_handler)]
#[on_html(".result__title",title_handler)]

struct Scraper {}

impl Scraper {
    // Print webpage status
    async fn response_handler(&self,response: Response) -> Result<()> {
        println!("Status {}",response.status);
        Ok(())
    }

    async fn title_handler(&self,_: Response,el: Element) -> Result<()> {
        // Get text of element
        let title_data = el.children();
        let title_text = title_data.first().unwrap().text().unwrap();
        println!("Result is {}",title_text);
        Ok(())
    }
}

// Run scraper to get info from https://duckduckgo.com/?t=ffab&q=rust&ia=web
async fn one_scrape() -> Result<()> {
    let scraper = Scraper {};
    scraper.run(Opts::new().with_urls(ENTRY_PREFIX.to_vec()).with_threads(1)).await
}

#[derive(Clone,Lens)]
struct Init {
    tag: String,}


fn build_ui() -> impl Widget<Init> {
    // Search Box
    let l_search = Label::new("Search: ");
    let tb_search = TextBox::new()
        .with_placeholder("Enter tag to search")
        .lens(Init::tag);
    let search = Flex::row()
        .with_child(l_search)
        .with_child(tb_search);

    // Describe layout of UI
    let layout = Flex::column()
        .with_child(search);
    
    Align::centered(layout)
}

#[async_std::main]
async fn main() -> Result<()> {
    // Describe the main window
    let main_window = WindowDesc::new(build_ui())
        .title("Title Tracker")
        .window_size((400.0,400.0));

    // Create starting app state
    let init_state = Init {
        tag: String::from("#"),};

    // Start application
    AppLauncher::with_window(main_window)
        .launch(init_state)
        .expect("Failed to launch application");

    one_scrape().await
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)