Визуализируйте тысячи / миллионы раз с помощью 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");