人人都会AI编程

4.2 两种核心通信模式

更新时间:2026-07-11

在 Tauri 应用中,前端(WebView)与后端(Rust)之间的通信是单向且受限的——前端无法直接调用 Rust 函数,必须通过 Tauri 提供的 IPC 管道。这套管道本质上支持两种模式:命令事件。理解它们的区别和适用场景,是写出高效 Tauri 应用的关键。


1. 命令模式(Commands)

命令是前端主动调用后端最常见的方式。Rust 函数通过 #[tauri::command] 注解标记,前端使用 invoke() 调用,像调用远程 API 一样传参和接收返回值。

特点

  • 请求-响应:前端发送一个调用,后端执行后返回结果(或被拒绝)。
  • 同步调用:前端 await invoke(...) 会等待 Rust 函数执行完成。
  • 强类型序列化:参数和返回值自动通过 serde 进行序列化/反序列化,传递结构体、字符串、数字等类型都很方便。

示例

// Rust 后端
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}
// 前端调用
const greeting = await invoke('greet', { name: 'Tauri' });
console.log(greeting); // "Hello, Tauri!"

适用场景

  • 读取/写入文件
  • 执行数据库查询
  • 调用系统 API 并同步获取结果
  • 任何需要“问一个问题,立刻得到答案”的操作

2. 事件模式(Events)

事件模式用于单向推送消息,特别适合后端主动通知前端的场景。Rust 端可以通过 app_handle.emit() 发送事件,前端用 listen() 订阅并接收。

特点

  • 发布-订阅:后端随时发射事件,前端监听并处理,不需要等待响应。
  • 多对多传播:一个事件可以有多个监听者,也可以在前端和后端之间互相发送。
  • 异步松耦合:事件发射后不关心谁在监听或是否处理成功。

示例

// Rust 后端(在某个任务中)
app_handle.emit("progress", 42).unwrap();
// 前端订阅
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('progress', (event) => {
  console.log(`进度: ${event.payload}%`);
});

适用场景

  • 长时间运行任务的进度更新(下载、处理大文件)
  • 系统托盘菜单点击通知
  • 后端主动推送的日志、状态变化
  • 避免前端频繁轮询

如何选择?

  • 需要返回值命令模式。例如“查询用户数据”“验证密码”,前端期望一个确定的结果。
  • 无需返回值,只需通知事件模式。例如“下载进度更新”“应用进入后台”,前端仅需知道状态变化。
  • 混合使用:可以用命令启动一个异步任务,并在 Rust 端将任务的阶段性结果通过事件推送给前端。这样保持前端 UI 响应,同时避免阻塞。

Tauri 的这两种模式覆盖了绝大多数桌面应用的通信需求,且都建立在安全沙箱之上——命令需要显式注册,事件载荷也受类型限制,不会破坏前后端的隔离性。掌握它们,基本就掌握了 Tauri 的通信骨架。