You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:35:54