2.2 IPC传送带:命令调用的完整旅程


2.1 节认了层,本节跟着一次 invoke 走完全程。这条旅程是第 4 章(前端调用)、第 5 章(写命令)、第 6 章(权限检查)三章共用的时序基准——以后任何"调用没生效""参数没对上"的排错,都从这条传送带上找断点。

出发前:命令怎么登记

传送带能转,先要有运单登记。Rust 侧两步:给函数贴 #[tauri::command] 标记,再把函数名交给启动时的路由宏:

#[tauri::command] fn add_note(title: String, body: String) -> Result<Note, String> { let note = Note { id: next_id(), title, body, created_at: now() }; save_to_disk(&note)?; Ok(note) } pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![add_note, greet]) .run(tauri::generate_context!()) .expect("failed to run"); }

generate_handler! 在编译期生成一张"命令名到函数"的路由表。前端调用的字符串名字必须精确匹配函数名的蛇形转驼峰形式:add_note 在前端叫 addNote。漏登记或名字拼错,前端会收到"未找到命令"类错误——这是新手第一高频坑。

完整旅程:八站时序

前端按下保存按钮,await invoke('addNote', { title, body }) 执行,接下来依次发生:

八站里值得停下来的有四处。第二站,序列化:参数对象与返回值都是 JSON,Rust 侧的参数类型必须能从 JSON 反序列化(实现 Deserialize),返回值必须能序列化(实现 Serialize)——第 5 章的 serde 细节全在服务这一站。第三站,权限闸门:桥接层核对当前窗口是否被 Capabilities 授权调用此命令,未授权直接拒绝,函数体根本不会执行——这就是"默认拒绝"在运行时的样子。第六站,命名转换:Rust 蛇形参数 created_at 在前端对象里写作 created_at 的驼峰 createdAt,转换由宏自动完成;想关掉转换也可以显式指定 rename_all,但两端约定要一致。第八站,错误回传Err 分支同样走序列化,前端 await 拿到的是 rejected promise——错误处理的完整方案在第 5 章第 4 节。

事件的语义:不请自来的另一条带

命令是"前端问、芯答",事件是"双方随时喊话"。芯可以向前端广播进度、前端也能向芯发事件。什么时候用事件而不是命令?给一个可操作的判断:语义上需要"推送"或"多方接收"的用事件,需要"请求响应"的用命令。 反解析进度条就是典型——芯在后台解析,完成度不由前端请求产生,用事件推:

use tauri::Emitter; #[tauri::command] fn parse_big_file(app: tauri::AppHandle, path: String) -> Result<(), String> { for (i, chunk) in read_chunks(&path).enumerate() { process(chunk); if i % 50 == 0 { // 向所有窗口广播解析进度 let _ = app.emit("parse-progress", i as f32 / total(&path)); } } Ok(()) }
import { listen } from '@tauri-apps/api/event'; const unlisten = await listen('parse-progress', (event) => { bar.style.width = `${Math.round(event.payload * 100)}%`; }); // 组件卸载时取消订阅,否则监听器泄漏 onUnmounted(() => unlisten());

两个工程细节常被忽略:其一,listen 返回取消函数,组件卸载必须调用,否则窗口关了监听器还挂着;其二,事件广播没有回执,不能拿事件做需要确认的事——"前端通知芯开始解析"应该走命令,"芯汇报进度"才走事件。把两条通道的分工混起来,是状态同步类 bug 的头号来源。

一张选用对照表

需求形态 选用 理由
前端要拿到结果才能继续 命令 有响应、有错误回传
芯主动汇报进度或状态变化 事件 推送语义,无需请求方在场
多窗口同时感知同一变化 事件广播 一次发送各方可达
需要确保执行且可失败重试 命令 错误能被 await 捕获处理
单窗口定向通知 事件定向 指定标签投递,避免打扰他窗

本节要点回顾

  • 登记三件事:命令标记、路由宏挂载、前端驼峰命名,三者对齐传送带才通;
  • 八站旅程:序列化、权限闸门、路由、执行、回传,闸门在函数执行之前;
  • 命令与事件分工:请求响应走命令,推送广播走事件,混用是状态 bug 之源;
  • 监听器要退订:listen 返回的取消函数随组件卸载调用;
  • 序列化是通用语言:参数与错误都过 JSON,类型设计(第 5 章)为它服务。

传送带的机械结构清楚了。下一节端详壳体本身——三块系统 WebView 差在哪、怎么适配、怎么分别调试。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U