invoke 是前端与 Rust 后端通信的核心通道。通过它,你可以像调用普通异步函数一样,把参数传给 Rust,并拿回计算结果。整个过程受严格的类型检查和权限控制,既安全又直观。
基本用法
首先在前端安装 @tauri-apps/api,然后导入 invoke:
import { invoke } from '@tauri-apps/api/tauri';
调用一个名为 greet 的 Rust 命令:
invoke('greet', { name: 'World' })
.then((response) => console.log(response)) // "Hello, World!"
.catch((error) => console.error(error));
Rust 端对应的命令:
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
并在 main 函数中注册:
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
参数与返回值
invoke 的第二个参数是一个普通对象,其键名必须与 Rust 函数的参数名一致。Rust 函数可以接收任意实现了 serde::Deserialize 的类型,包括结构体:
#[derive(Deserialize)]
struct User {
name: String,
age: u8,
}
#[tauri::command]
fn update_user(user: User) -> String {
format!("User {} is {} years old", user.name, user.age)
}
前端调用:
invoke('update_user', { user: { name: 'Alice', age: 30 } });
返回值同样会自动序列化为 JSON 传给前端。你可以返回 String、数字、布尔值、对象、Vec<T> 等,只要它们实现了 serde::Serialize。
错误处理
Rust 命令如果返回 Result<T, E>,Tauri 会自动处理:Ok 值正常返回;Err 会被转换成前端 Promise 的 rejection。
在 Rust 中:
#[tauri::command]
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("Division by zero".into())
} else {
Ok(a / b)
}
}
前端捕获错误:
invoke('divide', { a: 10, b: 0 })
.catch((err) => console.error(err)); // "Division by zero"
异步命令
如果 Rust 命令需要执行耗时操作(如读写大文件、网络请求),可以声明为 async 函数:
#[tauri::command]
async fn fetch_data(url: String) -> Result<String, String> {
let response = reqwest::get(&url).await.map_err(|e| e.to_string())?;
let body = response.text().await.map_err(|e| e.to_string())?;
Ok(body)
}
前端仍然使用 invoke,无需任何更改,它始终返回 Promise。
类型映射速查
| 前端传递 | Rust 接收 |
|--------------------|---------------|
| "hello" | String |
| 42 | i32, u32, f64 等 |
| true / false | bool |
| [1, 2, 3] | Vec<T> |
| { key: "value" } | 结构体或 HashMap |
| null | Option<T> |
安全与权限
invoke 调用的命令必须已在 Rust 中显式注册,并且前端无法构造任意系统调用。所有参数都经过反序列化校验,避免了命令注入。此外,你可以通过 Tauri 的权限系统进一步限制哪些窗口或 URL 可以调用特定命令,这为多窗口应用提供了细粒度的安全控制。
一句话总结:invoke 让前端与 Rust 之间的调用像本地函数一样自然,同时保持了类型安全和权限控制。