Визуализируйте тысячи / миллионы раз с помощью React и Tauri (ржавчина)

Я изучаю Rust. Я создаю настольное приложение, которое читает тысячи / миллион строк данных в файле csv, а затем передает их одну за другой с помощью таури. event.

Результат: Rust без проблем прочитал файл (менее 5 секунд). Что касается внешнего интерфейса, мое приложение React, похоже, не успевает за событиями. На экране altitude значение обновляется периодически.

Как справиться с этой ситуацией - React? или что я сделал не так?

Реагирующая сторона:

      // App.js

import { listen } from '@tauri-apps/api/event';
import { useEffect, useCallback, useState } from 'react';
import { invoke } from '@tauri-apps/api/tauri'

const App = () => {
  const [altitude, setAltitude] = useState("0");

  useEffect(() => {
    listen('rust-event', myCallback)
  }, [])

  const myCallback = useCallback((e) => {
    console.log(e);
    setAltitude(e.payload);
  },[])

  const handleClick = async () => {
    invoke('my_custom_command').catch(error => console.log(error));
  };

  return (
    <div>
        <button onClick={handleClick}>Click Me To Start Fetching!</button>
        <span>{altitude}</span>
    </div>
  );
}

export default App;

Сторона Тельца:

      // main.rs
use arrow::csv;
use arrow::datatypes::{DataType, Field, Schema};
use std::fs::File;
use std::sync::Arc;
use arrow::array::{StringArray, ArrayRef};

#[tauri::command]
async fn my_custom_command(window: tauri::Window) {
  let schema = Schema::new(vec![
    Field::new("altitude", DataType::Utf8, false)
  ]);

  // Open file
  let file = File::open("src/data.csv").unwrap();

  // Get csv Reader using schema
  let mut csv = csv::Reader::new(file, Arc::new(schema), true, None, 1, None, None);

    // Loop through each row
    while let Some(m) = csv.next() {
      let n = m.unwrap();
      // Get reference of array of a column
      let col: &ArrayRef = n.column(0);
      // Cast the reference of array to array of string
      let col = col.as_any().downcast_ref::<StringArray>().unwrap();
      // Get value from the array using index
      let v = col.value(0);
      println!("{}", col.value(0));
      
      // Send each value through an event
      window
        .emit("rust-event", v)
        .expect("failed to emit");
    }
}

fn main() {
  tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![my_custom_command])
    .run(tauri::generate_context!())
    .expect("failed to run app");
}

2 ответа

Я лично не предлагаю, что вы делаете, так как вы можете получить переполнение стека.

Лучше всего было бы испускать их в пакетном режиме, вы можете заполнить локальный буфер, когда есть X элементов (или достигнут конец), испустить событие и очистить буфер.

Пример

      #[tauri::command]
async fn my_custom_command(window: tauri::Window) {
  // Your code
  // [...]

  // send 20 elements in the Vec (array)
  let should_trigger_at = 20;
  // local buffer
  let local_buffer: Vec<String> = Vec::new();

  // Loop through each row
  while let Some(m) = csv.next() {
    let n = m.unwrap();
    // Get reference of array of a column
    let col: &ArrayRef = n.column(0);
    // Cast the reference of array to array of string
    let col = col.as_any().downcast_ref::<StringArray>().unwrap();
    // Get value from the array using index
    let v = col.value(0);
    println!("{}", col.value(0));

    // add the value in the buffer
    local_buffer.push(col.value(0));

    if local_buffer.len() == should_trigger_at {
      // Send each value through an event
      window
        .emit("rust-event", local_buffer)
        .expect("failed to emit");

      // reset local buffer
      local_buffer = Vec::new();
    }
  }
  // if buffer not empty, lets emit the values
  if local_buffer.len() > 0 {
    window
      .emit("rust-event", local_buffer)
      .expect("failed to emit");
  }

  // [...]
  // Your code
}

Обратите внимание ; это отправит Array of String в веб-просмотр вместо String.

Что ж, думаю, Rust слишком быстр :) React не справляется со скоростью.

Я замедляю генерирование событий с помощью settimeout rust lib, и пока я им доволен.

      // Before emit an event, delay it 100 microsecond;
set_timeout(Duration::from_micros(100)).await;

window
        .emit("rust-event", v)
        .expect("failed to emit");
Другие вопросы по тегам