Unable to change async rust code for asynchronous Tauri

I am struggling with the async code with Tauri. The code itself works just fine outside of the tauri application, however when I tried implementing the code I made inside of Tauri everything broke. I am pretty new to Tauri, so any help would be greatly appreciated!

Here’s the code:

#![cfg_attr(all(not(debug_assertions), target_os = "windows"),windows_subsystem = "windows")]

use tauri::Manager;
use tokio::sync::mpsc;
use tokio::sync::Mutex;
use tracing::info;
use tracing_subscriber;
use scraper::{Html, Selector};
use std::time::Instant;
use url::Url;

struct AsyncProcInputTx {
    inner: Mutex<mpsc::Sender<String>>,
}
#[tokio::main]
async fn main() {
    tracing_subscriber::fmt::init();

    let (async_proc_input_tx, async_proc_input_rx) = mpsc::channel(1);
    let (async_proc_output_tx, mut async_proc_output_rx) = mpsc::channel(1);

    tauri::Builder::default()
        .manage(AsyncProcInputTx {
            inner: Mutex::new(async_proc_input_tx),
        })
        .invoke_handler(tauri::generate_handler![js2rs])
        .setup(|app| {
            tauri::async_runtime::spawn(async move {
                async_process_model(
                    async_proc_input_rx,
                    async_proc_output_tx,
                ).await
            });

            let app_handle = app.handle();
            tauri::async_runtime::spawn(async move {
                loop {
                    if let Some(output) = async_proc_output_rx.recv().await {
                        rs2js(output, &app_handle);
                    }
                }
            });

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

fn rs2js<R: tauri::Runtime>(message: String, manager: &impl Manager<R>) {
    info!(?message, "rs2js");
    manager
        .emit_all("rs2js", format!("rs: {}", message))
        .unwrap();
}

#[tauri::command]
async fn js2rs(
    state: tauri::State<'_, AsyncProcInputTx>,
) -> Result<(), String> {
    let async_proc_input_tx = state.inner.lock().await;
    let start = Instant::now();

    // Using a more efficient client configuration with reqwest
    let client = reqwest::Client::builder()
        .tcp_nodelay(true)
        .build()?;

    let body = client
        .get("https://finance.yahoo.com/topic/stock-market-news/")
        .send()
        .await?
        .text()
        .await?;

    let document = Html::parse_document(&body);
    let document = document.read().unwrap();
    // Corrected selector for headlines on Yahoo Finance
    let selector = Selector::parse(r#"h3[class="Mb(5px)"]"#)?;
    let selector_link = Selector::parse("a")?;

    let mut tasks = vec![];
    let line = "-".repeat(80);

    for element in document.select(&selector) {
        let headline = element.text().collect::<Vec<_>>().join(""); // Join the text fragments into a single string
        if let Some(link) = element.select(&selector_link).next() {
            if let Some(href) = link.value().attr("href") {
                let href = Url::parse("https://finance.yahoo.com")?.join(href)?.as_str().to_owned();
                let client = client.clone();
                let line_clone = line.clone(); // Clone the line variable for each task
                let task = tokio::spawn(async move {
                    match get_article(&client, &href).await {
                        Ok(article_text) => {
                            info!("Headline: {}nURL: {}n, Text: {}nArticle: {}n", headline, href, line_clone, article_text);
                            info!("{}", line_clone);
                        }
                        Err(e) => info!("Failed to get article: {}", e),
                    }
                });
                tasks.push(task);
            }
        }
    }

    for task in tasks {
        task.await?;
    }

    let end = Instant::now();
    let duration = end.duration_since(start);
    info!("Request took: {:?}", duration);

    async_proc_input_tx
        .send("Pass".to_string())
        .await
        .map_err(|e| e.to_string());
    Ok(())
}




async fn get_article(client: &reqwest::Client, url: &str) -> Result<String, Box<dyn std::error::Error>> {
    let body = client
        .get(url)
        .send()
        .await?
        .text()
        .await?;

    let document = Html::parse_document(&body);
    let selector = Selector::parse(r#"div[class="caas-body"]"#)?;

    let mut text = String::new();
    for element in document.select(&selector) {
        text.push_str(&element.text().collect::<Vec<_>>().join(""));
    }
    Ok(text)
}

async fn async_process_model(
    mut input_rx: mpsc::Receiver<String>,
    output_tx: mpsc::Sender<String>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    while let Some(input) = input_rx.recv().await {
        let output = input;
        output_tx.send(output).await?;
    }

    Ok(())
}

Here are the errors:

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:70:17
   |
70 |         .build()?;
   |                 ^ the trait `From<reqwest::Error>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, reqwest::Error>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, reqwest::Error>>`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:75:15
   |
75 |         .await?
   |               ^ the trait `From<reqwest::Error>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, reqwest::Error>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, reqwest::Error>>`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:77:15
   |
77 |         .await?;
   |               ^ the trait `From<reqwest::Error>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, reqwest::Error>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, reqwest::Error>>`

error[E0599]: no method named `read` found for struct `scraper::Html` in the current scope
  --> src/main.rs:80:29
   |
80 |     let document = document.read().unwrap();
   |                             ^^^^ method not found in `Html`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:82:61
   |
82 |     let selector = Selector::parse(r#"h3[class="Mb(5px)"]"#)?;
   |                                                             ^ the trait `From<SelectorErrorKind<'_>>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, SelectorErrorKind<'_>>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, SelectorErrorKind<'_>>>`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:83:45
   |
83 |     let selector_link = Selector::parse("a")?;
   |                                             ^ the trait `From<SelectorErrorKind<'_>>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, SelectorErrorKind<'_>>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, SelectorErrorKind<'_>>>`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:92:67
   |
92 |                 let href = Url::parse("https://finance.yahoo.com")?.join(href)?.as_str().to_owned();
   |                                                                   ^ the trait `From<url::ParseError>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, url::ParseError>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, url::ParseError>>`

error[E0277]: `?` couldn't convert the error to `String`
  --> src/main.rs:92:79
   |
92 |                 let href = Url::parse("https://finance.yahoo.com")?.join(href)?.as_str().to_owned();
   |                                                                               ^ the trait `From<url::ParseError>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, url::ParseError>>`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `From<T>`:
             <String as From<char>>
             <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
             <String as From<Box<str>>>
             <String as From<AssetKey>>
             <String as From<Cow<'a, str>>>
             <String as From<tauri::Url>>
             <String as From<uuid::Uuid>>
             <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
           and 3 others
   = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, url::ParseError>>`

error[E0277]: `?` couldn't convert the error to `String`
   --> src/main.rs:110:19
    |
110 |         task.await?;
    |                   ^ the trait `From<tokio::task::JoinError>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual<Result<Infallible, tokio::task::JoinError>>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
              <String as From<char>>
              <String as From<tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
              <String as From<Box<str>>>
              <String as From<AssetKey>>
              <String as From<Cow<'a, str>>>
              <String as From<tauri::Url>>
              <String as From<uuid::Uuid>>
              <String as From<&'a tendril::tendril::Tendril<tendril::fmt::UTF8, A>>>
            and 3 others
    = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, tokio::task::JoinError>>`

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `news-screener` (bin "news-screener") due to 9 previous errors

I tried changing the code through various different ways but every time I switched to async Tauri refused to accept any of my solutions. What should’ve happened is when I invoked the js2rs function the code would fetch the latest articles of yahoo and log them.

New contributor

Maxim Gannota is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật