使用React和Tauri (rust)渲染数千/数百万次



我正在学习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");
}

我个人不建议你这样做,因为你可能会得到堆栈溢出。

最好是批处理它们,您可以填充一个局部缓冲区,当有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到Webview而不是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");

最新更新