tauri学习(3)-前端调用Rust代码
接上节继续,今天研究tauri中,前端如何调用Rust代码。
一、无返回值&无传参
main.rs中加1个hello方法:
然后在main方法中,参考下图暴露hello1:
Rust代码准备好之后,前端(假设是react框架)就能调用了:
import { invoke } from "@tauri-apps/api/tauri"
先引入invoke方法,然后在需要的地方:
运行效果:
二、有传参
/** * 可传参 */ #[tauri::command] fn hello2(msg: String) { println!("hello-2 {}!", msg); }
多个方法暴露,参考下图:
前端调用:
<button onClick={() => invoke('hello2', { msg: "jimmy" })}>hello2</button>
三、有传参&有返回值
/** * 有传参,带返回值 */ #[tauri::command] fn hello3(msg: String) -> String { format!("hello-3 {}", msg) }
前端调用:
let hello3 = (message: String) => { invoke("hello3", { msg: message }).then((message) => console.log(message)) }
四、返回复杂对象
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 }) }
前端调用:
let get_person = (name: String, age: Number) => { invoke("get_person", { name, age }).then((person) => console.log(person)) }
五、性能测试
很多功能,既然原生js与rust都能实现,谁的性能更高?
还是用经典的fibonacci做为示例:
/** * 测试性能 */ #[tauri::command] fn fibonacci(n: i32) -> i32 { if n <= 1 { 1 } else { fibonacci(n - 1) + fibonacci(n - 2) } }
前端:
// 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代码:
/** * 异常处理 */ #[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)) } }
前端调用:
let is_valid_age = (age: Number) => { invoke("is_valid_age", { age }) .then((msg) => console.log(msg)) .catch((err) => console.error(err)) }
七、Rust异步处理
/** * 异步方法 */ #[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的套路处理:
let async_test = () => { invoke("method_1").then((result) => { console.log("result:", result ); }) }
Rust终端输出结果:
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对象
#[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的连接状态是否正常,就可以用上这个
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
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。