【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 才会返回,后续代码才会执行。
相关推荐
IT_陈寒3 分钟前
Java集合的这个坑,我调试了整整3小时才爬出来
前端·人工智能·后端
前端老石人42 分钟前
前端网站换肤功能的 3 种实现方案
开发语言·前端·css·html
冴羽yayujs44 分钟前
2026 年的 JavaScript 已经不是你认识的 JavaScript 了
前端·javascript
小灰灰搞电子1 小时前
PyQt QWebChannel详解-C++与Web页面的无缝双向通信
前端·pyqt
M ? A1 小时前
你的 Vue v-for,VuReact 会编译成什么样的 React 代码?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
午安~婉1 小时前
Electron桌面应用(续3)
前端·javascript·electron·重构通用模型·异步可迭代对象
W.A委员会1 小时前
伪类与伪元素
前端·javascript·css
午安~婉1 小时前
Electron桌面应用(续2)
前端·javascript·electron·路由守卫·优化llm返回的内容
eEKI DAND1 小时前
一个比 Nginx 还简单的 Web 服务器
服务器·前端·nginx
Highcharts.js8 小时前
Highcharts 云端渲染的真相:交互式图表与服务器端生成的边界
前端·信息可视化·服务器渲染·highcharts·图表渲染