在Tauri中通过Rust发送全局事件失败的求助
问题:Rust线程发送Tauri全局事件无法更新前端文本
我是Rust和Tauri的新手,使用cargo create-tauri-app创建了一个应用,想要在Rust中添加线程发送全局事件,以此修改前端文本内容,但该功能无法正常运行。以下是我的相关代码:
index.html(仅添加了p元素#test-msg)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="stylesheet" href="styles.css" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Tauri App</title> <script type="module" src="/main.js" defer></script> </head> <body> <main class="container"> <h1>Welcome to Tauri</h1> <div class="row"> <a href="https://tauri.app" target="_blank"> <img src="/assets/tauri.svg" class="logo tauri" alt="Tauri logo" /> </a> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank" > <img src="/assets/javascript.svg" class="logo vanilla" alt="JavaScript logo" /> </a> </div> <p>Click on the Tauri logo to learn more about the framework</p> <form class="row" id="greet-form"> <input id="greet-input" placeholder="Enter a name..." /> <button type="submit">Greet</button> </form> <p id="greet-msg">Hallo1</p> <p id="test-msg">Hallo2</p> </main> </body> </html>
main.js(添加了testMsgEl并监听事件)
const { invoke } = window.__TAURI__.core; const { listen } = window.__TAURI__.event.listen; let greetInputEl; let greetMsgEl; let testMsgEl; async function greet() { greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value }); } listen<String> ('emit_from_rust', (event) => { testMsgEl.textContent = event.payload; }); window.addEventListener("DOMContentLoaded", () => { greetInputEl = document.querySelector("#greet-input"); greetMsgEl = document.querySelector("#greet-msg"); testMsgEl = document.querySelector("#test-msg"); document.querySelector("#greet-form").addEventListener("submit", (e) => { e.preventDefault(); greet(); }); });
lib.rs(添加了test_emit函数并通过.setup启动)
use std::{thread::sleep, time::Duration}; use tauri::{AppHandle, Emitter}; #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } fn test_emit(handle: AppHandle) { std::thread::spawn(move || { for i in 1..4 { sleep(Duration::from_secs(1)); handle.emit("emit_from_rust", &format!("{i}!")).unwrap(); } }); } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .invoke_handler(tauri::generate_handler![greet]) .setup(|app| { let handle = app.handle().clone(); test_emit(handle); Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri application"); }
解决方案
问题集中在前端代码的两处关键错误,修复后即可正常运行:
1. 修复事件监听的导入与执行时机
- 导入错误:
const { listen } = window.__TAURI__.event.listen;应改为const { listen } = window.__TAURI__.event; - 执行时机错误:原代码中
listen调用在DOM加载完成前执行,此时testMsgEl还未被赋值(处于undefined状态),回调赋值会触发错误。需将监听逻辑移到DOMContentLoaded回调内部。 - JavaScript无需指定泛型
<String>,直接移除该部分。
修改后的main.js:
const { invoke } = window.__TAURI__.core; const { listen } = window.__TAURI__.event; let greetInputEl; let greetMsgEl; let testMsgEl; async function greet() { greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value }); } window.addEventListener("DOMContentLoaded", () => { greetInputEl = document.querySelector("#greet-input"); greetMsgEl = document.querySelector("#greet-msg"); testMsgEl = document.querySelector("#test-msg"); // 将事件监听移到DOM加载完成后执行 listen('emit_from_rust', (event) => { testMsgEl.textContent = event.payload; }); document.querySelector("#greet-form").addEventListener("submit", (e) => { e.preventDefault(); greet(); }); });
2. Rust代码优化(可选)
Rust逻辑本身无功能性错误,但unwrap()会在事件发送失败时直接panic,建议替换为expect()添加调试信息:
handle.emit("emit_from_rust", &format!("{i}!")) .expect("Failed to emit event to frontend");
完成修改后重启应用,即可看到#test-msg元素的文本每隔1秒更新一次,依次显示1!、2!、3!。
内容的提问来源于stack exchange,提问作者DeepKling
相关产品推荐
相关产品推荐

