Skip to content

IPC 通信

Tauri 的 IPC 是异步消息传递。前端和核心进程交换可序列化的请求与响应。

主要原语:

  • Command:前端调用 Rust 函数,适合请求响应。
  • Event:单向通知,适合生命周期和状态变化。
  • Channel:适合分块流式数据。

Command

Rust 侧用 #[tauri::command] 注册函数:

rust
#[tauri::command]
fn app_version() -> String {
    env!("CARGO_PKG_VERSION").into()
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![app_version])
        .run(tauri::generate_context!())
        .expect("error while running tauri application")
}

前端调用:

ts
import { invoke } from '@tauri-apps/api/core'

const version = await invoke<string>('app_version')

参数以 JSON 对象传递。Rust 参数名是 snake_case 时,前端使用 camelCase

rust
#[tauri::command]
fn settings_set(key: String, value: String) -> Result<(), String> {
    if key.is_empty() || value.is_empty() {
        return Err("Invalid settings".into())
    }

    Ok(())
}
ts
await invoke('settings_set', { key: 'theme', value: 'dark' })

返回值需要实现 serde::Serialize。可能失败时返回 Result,前端 invoke 会变成 Promise reject。

同步 Command 默认跑在主线程。耗时逻辑应写成 async,由运行时调度到独立任务。

多个 Command 必须在同一次 generate_handler! 中注册,后一次 invoke_handler 会覆盖前一次。

Event

Event 没有返回值,也不做类型约束,只传 JSON。

前端发送:

ts
import { emit, listen } from '@tauri-apps/api/event'

await emit('download:progress', { percent: 50 })

const unlisten = await listen<{ percent: number }>('download:progress', (event) => {
  console.log(event.payload.percent)
})

unlisten()

Rust 侧也可以 listen / emit。组件卸载时要取消监听,避免重复回调。

高吞吐、有序的流式数据优先用 Channel,不要用 Event 模拟传输通道。

命名

推荐使用命名空间:

bash
app_version
settings_get
settings_set
file_open
download:progress

Command 名称来自 Rust 函数名,保持具体。避免 messageeventinvoke 这类万能通道。

封装建议

  • 前端通过 @tauri-apps/api 调用,不直接依赖 window.__TAURI__
  • 一个业务能力对应一个明确 Command。
  • handler 内做参数校验和服务调用,复杂逻辑放到独立 Rust 模块。
  • 前端拿到的是普通数据,不是 Rust 对象引用。
  • 自定义 Command 默认对所有窗口开放;需要收紧时在 capabilitiesAppManifest::commands 中声明允许列表。

基于 MIT 许可发布