Llamar al Frontend desde Rust
Llamar al Frontend desde Rust
Hay tres formas de comunicarse desde Rust hacia el frontend.
Sistema de eventos
Eventos globales
Llegan a todas las ventanas:
use tauri::{AppHandle, Emitter};
#[tauri::command]
fn start_download(app: AppHandle, url: String) {
// Logica de descarga...
app.emit("download-started", &url).unwrap();
app.emit("download-progress", 50).unwrap();
app.emit("download-complete", true).unwrap();
}
Escuchar en JavaScript:
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('download-progress', (event) => {
console.log(`Progreso: ${event.payload}%`);
});
// Dejar de escuchar al desmontar el componente
unlisten();
Eventos a una ventana especifica
use tauri::{AppHandle, Emitter};
#[tauri::command]
fn notify_settings(app: AppHandle) {
app.emit_to("settings", "config-updated", "tema oscuro").unwrap();
}
Eventos con filtro
use tauri::{AppHandle, Emitter, EventTarget};
#[tauri::command]
fn notify_admins(app: AppHandle) {
app.emit_filter("admin-alert", "Alerta!", |target| {
matches!(target, EventTarget::WebviewWindow { label } if label.starts_with("admin"))
}).unwrap();
}
Escuchar eventos del frontend en Rust
use tauri::Listener;
pub fn run() {
tauri::Builder::default()
.setup(|app| {
app.listen("file-selected", |event| {
println!("Archivo: {}", event.payload());
});
Ok(())
})
.run(tauri::generate_context!())
.expect("error");
}
Emitir desde JavaScript
import { emit, emitTo } from '@tauri-apps/api/event';
// Global
await emit('file-selected', '/ruta/archivo.txt');
// A una ventana especifica
await emitTo('main', 'update-requested', { key: 'theme' });
Canales
Para transmisiones de alto volumen donde el orden importa. Mas rapidos que eventos para datos frecuentes:
use tauri::ipc::Channel;
use serde::Serialize;
#[derive(Serialize)]
struct LogEntry {
level: String,
message: String,
}
#[tauri::command]
async fn watch_logs(on_log: Channel<LogEntry>) {
loop {
let entry = LogEntry {
level: "info".into(),
message: "Proceso activo".into(),
};
if on_log.send(entry).is_err() {
break; // Frontend desconectado
}
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
}
Evaluar JavaScript
Ejecuta codigo JS directamente en el webview:
use tauri::webview::WebviewWindow;
#[tauri::command]
async fn show_alert(window: WebviewWindow) {
window.eval("alert('Hola desde Rust!')").unwrap();
}
Usa eval con cuidado — prefiere eventos o canales para comunicacion estructurada. eval es util para casos especificos como manipular el DOM directamente.
Cuando usar cada mecanismo
| Mecanismo | Uso ideal |
|---|---|
| Eventos globales | Notificar cambios de estado a todas las ventanas |
| Eventos dirigidos | Notificar a una ventana especifica |
| Canales | Streaming de datos frecuentes (logs, progreso) |
| eval | Manipulacion directa del DOM (casos excepcionales) |
Importante: limpieza
Siempre llama unlisten() al desmontar componentes para evitar memory leaks:
// React
useEffect(() => {
const unlistenPromise = listen('my-event', handler);
return () => { unlistenPromise.then(fn => fn()); };
}, []);
Resumen
app.emit()envia eventos globales a todas las ventanasapp.emit_to()envia a una ventana especificalisten()en JavaScript para escuchar eventos de Rust- Canales para datos frecuentes donde el orden importa
eval()para ejecutar JS directo (usar con moderacion)- Siempre limpiar listeners al desmontar componentes
← Llamar Rust desde el Frontend | Indice | Siguiente: Gestion de Estado →