【Tauri】Tauri中Channel的使用

Channel 在 Tauri 中是前端与 Rust 后端进行异步消息通信的桥梁,常用于事件流(如 SSE、WebSocket、长连接)场景。


作用

  • 前端 JS 通过 Channel 实例接收后端 Rust 主动推送的消息。
  • 适合用在"事件驱动"或"流式数据"场景,比如服务端事件(SSE)、实时日志、推送等。

一般用法

1. 前端创建 Channel 并传给 Rust

js 复制代码
import { Channel, invoke } from '@tauri-apps/api/core';

const chan = new Channel();
chan.onmessage = (msg) => {
  // 这里处理 Rust 主动推送的消息
  console.log('收到消息:', msg);
};

const res = await invoke('your_rust_command', { chan }); // 划重点:res何时被打印??

2. Rust 端接收 Channel 并发送消息

rust 复制代码
#[tauri::command]
async fn your_rust_command(chan: tauri::ipc::Channel) {
    // 发送消息到前端
    chan.send("hello from rust!").unwrap();
    // 或循环推送事件
    loop {
        chan.send("实时数据").unwrap();
        tokio::time::sleep(Duration::from_secs(1)).await;
    }
}

问题一:channel 什么时候结束?

  • 只要不调用 destroy_client (即不关闭/移除该 SSE 客户端),Rust 端的 sse_open_stream 里的 loop 就会一直运行,chan.send(...) 会不断推送消息到前端,channel 不会结束

  • 只有当:

rust 复制代码
#[tauri::command]
pub async fn sse_close_stream(url: &str) -> Result<(), String> {
    destroy_client(url.to_string());
    Ok(())
}

问题2: 是不是只要连接一直在res就一直打印不出来,只有断了连接才会走后面的打印?

是的

  • 只要 Rust 端的 sse_open_stream 没有 break(即 SSE 连接还在),await invoke(...) 就会一直 pending,不会执行到 console.log(res)
  • 只有当 SSE 连接断开、出错,或者你主动调用 destroy_client,Rust 端的循环 break,函数返回,res 才会有值,console.log(res) 才会执行。

实例

下面代码中有四个debugger,尝试猜测一下进断点先后顺序

js 复制代码
    const startSSE = async () => {
        const req_url = `${getRcsApiPrefix()}/sse/connect?clientKey=${clientKey}`;
        try {
            let flag = true;
            const chan = new Channel();
            chan.onmessage = async (eve) => {
                debugger // 1
                if (!flag) return;
                const data = JSON.parse(eve);
                if (callback && !callback(data)) {
                    flag = false;
                    await invoke("sse_close_stream", { url: req_url });
                }
            };
            debugger //2
            const res = await invoke("sse_open_stream", { url: req_url, chan });
            console.log(res)
            debugger // 3
            if (res === 1 || (res === 2 && !flag)) {
                timer = setTimeout(() => { startSSE(); }, 25);
            } 
        } catch (error) {
            console.log(`SSE请求失败,尝试重连: ${error}, 时刻: ${new Date()}`);
            timer = setTimeout(() => { startSSE(); }, 3000);
        }
    }
    const closeSSE = async () => {
        debugger // 4
        const req_url = `${getRcsApiPrefix()}/sse/connect?clientKey=${clientKey}`;
        await invoke("sse_close_stream",{url: req_url});

    }

    onMounted(async () => {
        startSSE();
    });
    onUnmounted(async () => {
        sseConnections.clear();
        await closeSSE();
        clearTimeout(timer);
    });

答案:2143

  • 初始化时:先建立Channel,后请求sse_open_stream,先进2;
  • 建立连接后开始实时通信,进入chan.onmessage回调,进入1;
  • 一直通信,await invoke(...) 一直 pending;
  • 离开界面,调用closeSSE(),进入4;
  • 连接销毁,await invoke()结束,res被赋值,进入3。

总结

  • Channel 是 Tauri 前后端异步消息推送的桥梁
  • 前端用 chan.onmessage 监听消息,Rust 端用 chan.send() 主动推送。
  • 适合流式、事件驱动的数据通信。
  • channel 只要不 destroy_client 就不会结束,invoke 也不会返回。
  • 只有连接断开或 destroy_client 后,invoke 才会返回,后续代码才会执行。
相关推荐
咖啡星人k10 分钟前
从需求到交付:我用MonkeyCode的AI Agent完成了一个React数据看板
前端·人工智能·react.js·monkeycode
sxlishaobin13 分钟前
linux 自动清除日志 脚本
linux·服务器·前端
ZC跨境爬虫23 分钟前
跟着 MDN 学CSS day_37:(从文档流到粘性定位的底层原理)
前端·javascript·css·ui·html
IccBoY39 分钟前
NVM超详细全解教程:解决Node版本冲突(Win/Mac/Linux安装+使用+踩坑合集)
前端·node.js
wuhen_n42 分钟前
前端工程师进阶提示词工程实战
前端·langchain·ai编程
GISer_Jing1 小时前
Claude Code MCP Server 集成全解析
前端·人工智能·ai·架构
蚰蜒螟1 小时前
走进 Linux 内核:从 touch 命令到磁盘 inode 的完整旅程
java·linux·前端
因_崔斯汀1 小时前
用 AI 编程助手从零生成 3D 智慧校园数据大屏 —— Claude Code 实战全记录
前端
前端Hardy1 小时前
CSS 动画真的比 JS 快?Josh Comeau 做了组实验,结果跟直觉不一样
前端·javascript·后端
自进化Agent智能体1 小时前
MCP与Hooks:让AI Agent安全连接一切的治理框架
前端