1. 参数传递
Rust 命令可以接收基本类型(如 String、i32、bool)或序列化结构体作为参数。前端调用时传入一个 JSON 对象,Tauri 会自动反序列化成对应的 Rust 类型。
Rust 端定义命令:
#[tauri::command]
fn greet(name: String, age: u32) -> String {
format!("Hello, {}! You are {} years old.", name, age)
}
前端调用(使用 @tauri-apps/api):
import { invoke } from '@tauri-apps/api/core';
const result = await invoke('greet', { name: 'Alice', age: 30 });
console.log(result); // "Hello, Alice! You are 30 years old."
如果参数较多或结构固定,建议使用结构体:
#[derive(serde::Deserialize)]
struct User {
name: String,
age: u32,
}
#[tauri::command]
fn process_user(user: User) -> String {
format!("{} is {} years old", user.name, user.age)
}
前端只需传递与结构体字段匹配的对象即可,字段名必须一致(默认骆驼式命名)。
2. 返回值接收
命令的返回值类型会被自动序列化成 JSON,前端 invoke 返回一个 Promise,解析后得到对应的 JavaScript 值。
- 基本类型:
i32→number,String→string,Vec<T>→Array等。 - 复杂类型:只要实现了
Serialize,就能返回自定义结构体。
示例——返回一个结构体:
#[derive(serde::Serialize)]
struct FileInfo {
path: String,
size: u64,
}
#[tauri::command]
fn get_file_info(path: String) -> FileInfo {
// 假设获取到了信息
FileInfo { path, size: 1024 }
}
前端:
const fileInfo = await invoke<FileInfo>('get_file_info', { path: '/test.txt' });
console.log(fileInfo.size); // 1024
注意:你可以为 invoke 显式指定泛型类型,以获得更准确的 TypeScript 推导。
3. 错误捕获
Rust 命令中推荐返回 Result<T, E>,其中 E 可以是任何实现了 Serialize 的错误类型。Tauri 会自动将 Ok 值作为正常返回值,而 Err 值会被序列化后以 JavaScript 异常的形式抛出。
Rust 端:
#[tauri::command]
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("Division by zero".into())
} else {
Ok(a / b)
}
}
前端错误处理:
try {
const result = await invoke('divide', { a: 10, b: 0 });
console.log(result);
} catch (error) {
console.error(error); // "Division by zero"
}
你也可以定义更结构化的错误:
#[derive(Debug, serde::Serialize)]
struct MyError {
code: u32,
message: String,
}
#[tauri::command]
fn do_something() -> Result<(), MyError> {
Err(MyError { code: 1, message: "Something went wrong".into() })
}
前端捕获到的 error 将是一个包含 code 和 message 的字符串或对象(取决于序列化方式),你可以解析它并进行针对性处理。
实用要点
- 参数校验:Rust 的类型系统已强制校验,错误的数据类型会导致调用当场失败(Promise reject)。
- 命令注册:所有命令需要通过
.invoke_handler(tauri::generate_handler![greet, divide])注册到主构建器中,否则前端无法调用。 - 异步命令:如果命令内部需要执行耗时操作(如网络请求),可以定义为异步函数
async fn,避免阻塞主线程。前端调用方式不变,仍然是await invoke(...)。
通过这种方式,Tauri 让前后端之间的数据交换和错误传递变得高度统一——就像调用一个本地函数,只不过它跑在另一个进程里,但你几乎感知不到中间的序列化与 IPC 细节。