接上节继续,今天研究tauri中,前端如何调用Rust代码。
一、无返回值&无传参
main.rs中加1个hello方法:
然后在main方法中,参考下图暴露hello1:
Rust代码准备好之后,前端(假设是react框架)就能调用了:
代码语言:javascript复制import { invoke } from "@tauri-apps/api/tauri"
先引入invoke方法,然后在需要的地方:
运行效果:
二、有传参
代码语言:javascript复制/**
* 可传参
*/
#[tauri::command]
fn hello2(msg: String) {
println!("hello-2 {}!", msg);
}
多个方法暴露,参考下图:
前端调用:
代码语言:javascript复制<button onClick={() => invoke('hello2', { msg: "jimmy" })}>hello2</button>
三、有传参&有返回值
代码语言:javascript复制/**
* 有传参,带返回值
*/
#[tauri::command]
fn hello3(msg: String) -> String {
format!("hello-3 {}", msg)
}
前端调用:
代码语言:javascript复制 let hello3 = (message: String) => {
invoke("hello3", { msg: message }).then((message) => console.log(message))
}
四、返回复杂对象
代码语言:javascript复制use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct Person {
name: String,
age: i32,
}
/**
* 返回复杂对象
*/
#[tauri::command]
fn get_person(name: String, age: i32) -> Result<Person, String> {
Ok(Person { name, age })
}
前端调用:
代码语言:javascript复制let get_person = (name: String, age: Number) => {
invoke("get_person", { name, age }).then((person) => console.log(person))
}
五、性能测试
很多功能,既然原生js与rust都能实现,谁的性能更高?
还是用经典的fibonacci做为示例:
代码语言:javascript复制/**
* 测试性能
*/
#[tauri::command]
fn fibonacci(n: i32) -> i32 {
if n <= 1 {
1
} else {
fibonacci(n - 1) fibonacci(n - 2)
}
}
前端:
代码语言:javascript复制// js原生版的fibonacci (by:菩提树下的杨过 http://yjmyzz.cnblogs.com)
function fibonacci_js(n: number): number {
if (n <= 1) {
return 1;
}
return fibonacci_js(n - 2) fibonacci_js(n - 1);
}
function App() {
//js版fibonacci测试
let js_test = (n: number) => {
let begin = new Date().getTime();
let result = fibonacci_js(n);
let end = new Date().getTime();
console.log(`fibonacci_js(${n})t= ${result},t执行时间: ${end - begin} ms`);
}
//rust版fibonacci测试
let tauri_test = (n: number) => {
let begin = new Date().getTime();
invoke('fibonacci', { n }).then((result) => {
let end = new Date().getTime();
console.log(`fibonacci_tauri(${n})t= ${result},t执行时间: ${end - begin} ms`);
});
}
...
<button onClick={() => js_test(38)}>fibonacci_js</button>
<button onClick={() => tauri_test(38)}>fibonacci_tauri</button>
...
}
从输出耗时看,同样的硬件条件情况下,rust的实现,性能高于原生js,但略逊于wasm版本(可参见react rust webAssembly(wasm)示例 )
六、异常处理
Rust代码:
代码语言:javascript复制/**
* 异常处理
*/
#[tauri::command]
fn is_valid_age(age: i32) -> Result<String, String> {
if age > 0 && age < 150 {
Ok("pass".into())
} else {
Err(format!("age:{} invalid", age))
}
}
前端调用:
代码语言:javascript复制 let is_valid_age = (age: Number) => {
invoke("is_valid_age", { age })
.then((msg) => console.log(msg))
.catch((err) => console.error(err))
}
七、Rust异步处理
代码语言:javascript复制/**
* 异步方法
*/
#[tauri::command]
async fn method_1() -> String {
println!("method_1 is called");
//内部再调用另1个异步方法
let result = method_2();
//这里不会block,会继续执行下一句
println!("do another thing in method_1");
//这里会阻塞,直到method_2返回
let result = result.await;
println!("method_2 result:{} from method_1", result);
//返回method_2的结果
result
}
async fn method_2() -> String {
println!("method_2 is called");
//刻意停3秒【注:必须先use std::{thread, time};】
thread::sleep(time::Duration::from_secs(3));
format!("method_2 result")
}
前端调用时,并无特别之处,仍按promise的套路处理:
代码语言:javascript复制 let async_test = () => {
invoke("method_1").then((result) => {
console.log("result:", result
);
})
}
Rust终端输出结果:
代码语言:javascript复制method_1 is called
do another thing in method_1
method_2 is called
method_2 result:method_2 result from method_1
八、访问tauri应用的window对象
代码语言:javascript复制#[tauri::command]
async fn get_window_label(window: tauri::Window) {
println!(
"Window: {},is_fullscreen:{:?}",
window.label(), //获取应用窗口的label
window.is_fullscreen() //获取应用是否全屏
);
}
九、state管理
注:这里的state可不是react组件的state,而是指tauri应用内部的状态,比如应用查询数据库前,要先判断下db的连接状态是否正常,就可以用上这个
代码语言:javascript复制struct DatabaseState {
connnted: bool,
}
fn connect_db() -> DatabaseState {
DatabaseState { connnted: true }
}
#[tauri::command]
fn query_data(state: tauri::State<DatabaseState>) {
assert_eq!(state.connnted, true);
println!("query data success")
}
这里我们定义了一个DatabaseState,然后在connect_db方法里,模拟连接上db后,将connected状态置成true,然后在query_data方法中,先判断db是否连上了。
在main方法中,就可以管理状态:
参考文章:
https://tauri.app/v1/guides/features/command