Skip to content

IPC 通信

IPC(进程间通信)是连接前端 UI 和 Rust 后端的桥梁。灵动桌面框架提供了封装良好的 API 层来简化 IPC 调用。

invoke 调用流程

1. 定义 Rust Command

rust
// src-tauri/src/commands/system.rs
use crate::error::CommandError;

#[tauri::command]
pub fn greet(name: &str) -> Result<String, CommandError> {
    if name.is_empty() {
        return Err(CommandError::validation("姓名不能为空"));
    }
    Ok(format!("你好, {}!", name))
}

2. 注册 Command

rust
// src-tauri/src/lib.rs
tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![
        commands::system::greet,
        commands::system::get_system_info,
        commands::config::get_all_config,
        commands::config::get_config,
        commands::config::set_config,
        commands::config::delete_config,
    ])

3. 前端 API 封装

typescript
// src/lib/api/system.ts
import { invokeCommand } from './client'

export async function greet(name: string): Promise<string> {
  return invokeCommand<string>('greet', { name })
}

4. 在组件中使用

tsx
import { greet } from '@/lib/api'

function MyComponent() {
  const handleClick = async () => {
    const message = await greet('灵动')
    console.log(message) // "你好, 灵动!"
  }
  return <button onClick={handleClick}>打招呼</button>
}

API Client 封装

框架提供了统一的 invoke 封装,自动处理错误解析:

typescript
// src/lib/api/client.ts
import { invoke } from '@tauri-apps/api/core'

export async function invokeCommand<T>(
  cmd: string,
  args?: Record<string, unknown>
): Promise<T> {
  try {
    return await invoke<T>(cmd, args)
  } catch (error) {
    // 统一错误处理
    throw parseCommandError(error)
  }
}

useCommand Hook

typescript
// src/hooks/useCommand.ts
import { useState, useCallback } from 'react'
import { invokeCommand } from '@/lib/api/client'

export function useCommand<T>(cmd: string) {
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const execute = useCallback(async (args?: Record<string, unknown>) => {
    setLoading(true)
    setError(null)
    try {
      const result = await invokeCommand<T>(cmd, args)
      setData(result)
      return result
    } catch (e) {
      setError(String(e))
      throw e
    } finally {
      setLoading(false)
    }
  }, [cmd])

  return { data, loading, error, execute }
}

事件通信

除了请求-响应式的 invoke,还支持事件驱动的通信:

rust
// Rust 端发送事件
use tauri::Emitter;

app_handle.emit("update-available", version)?;
typescript
// 前端监听
import { listen } from '@tauri-apps/api/event'

const unlisten = await listen('update-available', (event) => {
  console.log('新版本:', event.payload)
})

// 清理监听
unlisten()

最佳实践

规范

  • 所有 invoke 调用必须封装到 src/lib/api/ 中,禁止在组件中直接使用 invoke()
  • 每个 Command 必须返回 Result<T, CommandError>,禁止使用 unwrap()
  • 大数据传输考虑分批次或使用事件流

基于 Tauri 2.x 构建的企业级桌面应用开发框架